Python
Official Unsent Python SDK for sending emails and managing contacts.
This guide shows how to install and use the official unsent Python SDK.
Initialize
Import the unsent class and initialize the client with your API key.
from unsent import unsent
# Initialize with raise_on_error=False to return errors as tuples
client = unsent("un_xxx", raise_on_error=False)Send an email
Now you can send an email. The SDK uses TypedDict definitions (like EmailCreate) to provide type hinting in your editor, but at runtime, you simply pass a standard Python dictionary.
Here is an example of sending a simple HTML email:
from unsent import unsent, types
client = unsent("un_xxx")
# Define the email payload
payload: types.EmailCreate = {
"to": "user@example.com",
"from": "no-reply@yourdomain.com",
"subject": "Welcome",
"html": "<strong>Hello!</strong>",
"headers": {"X-Campaign": "welcome"},
}
# Send the email
data, err = client.emails.send(payload)
if err:
print("Error:", err)
else:
print("Email sent:", data)Note
Unsent forwards your custom headers to SES. Only the X-Unsent-Email-ID and References headers are managed automatically by Unsent.
Attachments and scheduling
You can also send emails with attachments and schedule them for later delivery.
- Attachments: Provide a list of attachments, where each attachment has a
filenameandcontent(Base64 encoded string). - Scheduling: Use the
scheduledAtfield with adatetimeobject.
from datetime import datetime, timedelta
from unsent import types
payload: types.EmailCreate = {
"to": ["user1@example.com", "user2@example.com"],
"from": "no-reply@yourdomain.com",
"subject": "Report",
"text": "See attached.",
"attachments": [
{"filename": "report.txt", "content": "SGVsbG8gd29ybGQ="}, # Content must be Base64 encoded
],
"scheduledAt": datetime.utcnow() + timedelta(minutes=10), # Schedule for 10 minutes from now
}
data, err = client.emails.create(payload)Batch send
To send multiple emails efficiently in a single request, use the batch method.
items: list[types.EmailBatchItem] = [
{"to": "a@example.com", "from": "no-reply@yourdomain.com", "subject": "A", "html": "<p>A</p>"},
{"to": "b@example.com", "from": "no-reply@yourdomain.com", "subject": "B", "html": "<p>B</p>"},
]
data, err = client.emails.batch(items)Retrieve and manage emails
You can retrieve details of sent emails, update scheduled emails, or cancel them.
Get an email
Fetch the status and details of a specific email using its ID:
email, err = client.emails.get("email_123")Update schedule time
Change the scheduled delivery time for a pending email:
from datetime import datetime, timedelta
update: types.EmailUpdate = {"scheduledAt": datetime.utcnow() + timedelta(hours=1)}
data, err = client.emails.update("email_123", update)Cancel a scheduled email
Cancel a scheduled email so it won't be sent:
data, err = client.emails.cancel("email_123")List emails
Retrieve a list of sent emails with optional filters:
data, err = client.emails.list(
page=1,
limit=20,
start_date="2024-01-01T00:00:00Z",
end_date="2024-01-31T23:59:59Z",
domain_id="domain_id_123" # Can also be a list: ["id1", "id2"]
)Get email complaints
Retrieve email complaints with pagination:
data, err = client.emails.get_complaints(page=1, limit=20)Get email bounces
Retrieve email bounces with pagination:
data, err = client.emails.get_bounces(page=1, limit=20)Get email unsubscribes
Retrieve email unsubscribes with pagination:
data, err = client.emails.get_unsubscribes(page=1, limit=20)Contacts
Manage your contacts and organize them into contact books. All contact operations require a contact book ID (book_id).
List contacts
Retrieve contacts from a contact book with optional filters:
data, err = client.contacts.list(
"book_123",
page=1,
limit=20,
emails="user1@example.com,user2@example.com",
ids="contact_id_1,contact_id_2"
)Create a contact
Add a new contact to a specific contact book. You can include custom properties.
create: types.ContactCreate = {
"email": "user@example.com",
"firstName": "Jane",
"properties": {"plan": "pro"},
}
data, err = client.contacts.create("book_123", create)Get a contact
Retrieve a contact's details:
contact, err = client.contacts.get("book_123", "contact_456")Update a contact
Update a contact's information:
update: types.ContactUpdate = {"subscribed": False}
data, err = client.contacts.update("book_123", "contact_456", update)Upsert a contact
Use upsert to create a contact if they don't exist, or update them if they do.
upsert: types.ContactUpsert = {
"email": "user@example.com",
"firstName": "Jane",
}
data, err = client.contacts.upsert("book_123", "contact_456", upsert)Delete a contact
Remove a contact from a book:
data, err = client.contacts.delete("book_123", "contact_456")Campaigns
Campaigns allow you to send emails to all contacts in a specific contact book.
Create a campaign
Create a new campaign by defining its content and the target contact book.
campaign: types.CampaignCreate = {
"name": "Welcome Series",
"subject": "Welcome!",
"html": "<p>Thanks for joining us!</p>",
"from": "welcome@yourdomain.com",
"contactBookId": "book_123",
}
data, err = client.campaigns.create(campaign)Schedule a campaign
Schedule the campaign to be sent at a specific time.
schedule: types.CampaignSchedule = {
"scheduledAt": "2024-12-01T10:00:00Z"
}
data, err = client.campaigns.schedule("campaign_123", schedule)Pause and Resume
Control the delivery of your campaign.
# Pause
data, err = client.campaigns.pause("campaign_123")
# Resume
data, err = client.campaigns.resume("campaign_123")Domains
Manage your sending domains.
List domains
Get a list of all domains and their statuses.
data, err = client.domains.list()Create a domain
Register a new domain for sending.
domain: types.DomainCreate = {
"domain": "yourdomain.com",
"region": "us-east-1",
}
data, err = client.domains.create(domain)Verify a domain
Check the verification status of a domain.
data, err = client.domains.verify("domain_id_123")Suppressions
Manage your email suppression list (bounces, complaints, unsubscribes).
List suppressions
View email addresses on the suppression list with optional filters:
# List all suppressions
data, err = client.suppressions.list()
# Filter by reason
data, err = client.suppressions.list(
reason="HARD_BOUNCE", # Options: HARD_BOUNCE, COMPLAINT, MANUAL, UNSUBSCRIBE
page=1,
limit=20,
search="example.com"
)Add a suppression
Manually suppress an email address:
data, err = client.suppressions.add({
"email": "spam@example.com",
"reason": "MANUAL" # Options: HARD_BOUNCE, COMPLAINT, MANUAL, UNSUBSCRIBE
})Delete a suppression
Remove an email from the suppression list:
data, err = client.suppressions.delete("user@example.com")Error handling
The SDK supports two modes of error handling.
Raising Exceptions (Default)
By default, the client raises unsentHTTPError for non-2xx responses. This is useful for standard exception handling.
from unsent import unsent, unsentHTTPError
# Raises exceptions on errors (default)
client = unsent("un_xxx")
try:
data, _ = client.emails.get("email_123")
except unsentHTTPError as e:
print("Request failed:", e)Returning Error Tuples
If you prefer to check for errors in the return value instead of using try-except blocks, pass raise_on_error=False when initializing the client.
# Returns (None, error) instead of raising
client = unsent("un_xxx", raise_on_error=False)
data, err = client.emails.get("email_123")
if err:
print("Error:", err)
else:
print("Success:", data)