The official Python SDK for the Emailit Email API.
- Python 3.7+
- Requests 2.20+
pip install emailitfrom emailit import EmailitClient
client = EmailitClient("your_api_key")
email = client.emails.send({
"from": "hello@yourdomain.com",
"to": ["user@example.com"],
"subject": "Hello from Emailit",
"html": "<h1>Welcome!</h1><p>Thanks for signing up.</p>",
})
print(email.id) # em_abc123...
print(email.status) # pendingAll service methods return typed resource objects (Email, Domain, Contact, etc.) with direct attribute access -- just like the Stripe SDK.
| Service | Property | Description |
|---|---|---|
| Emails | client.emails |
Send, list, get, cancel, retry emails |
| Domains | client.domains |
Create, verify, list, manage sending domains |
| API Keys | client.api_keys |
Create, list, manage API keys |
| Audiences | client.audiences |
Create, list, manage audiences |
| Subscribers | client.subscribers |
Add, list, manage subscribers in audiences |
| Templates | client.templates |
Create, list, publish email templates |
| Suppressions | client.suppressions |
Create, list, manage suppressed addresses |
| Email Verifications | client.email_verifications |
Verify email addresses |
| Email Verification Lists | client.email_verification_lists |
Create, list, get results, export |
| Webhooks | client.webhooks |
Create, list, manage webhooks |
| Contacts | client.contacts |
Create, list, manage contacts |
| Events | client.events |
List and retrieve events |
email = client.emails.send({
"from": "hello@yourdomain.com",
"to": ["user@example.com"],
"subject": "Hello from Emailit",
"html": "<h1>Welcome!</h1>",
})
print(email.id)
print(email.status)email = client.emails.send({
"from": "hello@yourdomain.com",
"to": "user@example.com",
"template": "welcome_email",
"variables": {
"name": "John Doe",
"company": "Acme Inc",
},
})import base64
email = client.emails.send({
"from": "invoices@yourdomain.com",
"to": "customer@example.com",
"subject": "Your Invoice #12345",
"html": "<p>Please find your invoice attached.</p>",
"attachments": [
{
"filename": "invoice.pdf",
"content": base64.b64encode(open("invoice.pdf", "rb").read()).decode(),
"content_type": "application/pdf",
},
],
})email = client.emails.send({
"from": "reminders@yourdomain.com",
"to": "user@example.com",
"subject": "Appointment Reminder",
"html": "<p>Your appointment is tomorrow at 2 PM.</p>",
"scheduled_at": "2026-01-10T09:00:00Z",
})
print(email.status) # scheduled
print(email.scheduled_at) # 2026-01-10T09:00:00Zemails = client.emails.list({"page": 1, "limit": 10})
for email in emails:
print(f"{email.id} — {email.status}")
if emails.has_more():
# fetch next page
passclient.emails.cancel("em_abc123")
client.emails.retry("em_abc123")# Create a domain
domain = client.domains.create({
"name": "example.com",
"track_loads": True,
"track_clicks": True,
})
print(domain.id)
# Verify DNS
domain = client.domains.verify("sd_123")
# List all domains
domains = client.domains.list()
# Get a domain
domain = client.domains.get("sd_123")
# Update a domain
domain = client.domains.update("sd_123", {"track_clicks": False})
# Delete a domain
client.domains.delete("sd_123")# Create an API key
key = client.api_keys.create({
"name": "Production Key",
"scope": "full",
})
print(key.key) # only available on create
# List all API keys
keys = client.api_keys.list()
# Get an API key
key = client.api_keys.get("ak_123")
# Update an API key
client.api_keys.update("ak_123", {"name": "Renamed Key"})
# Delete an API key
client.api_keys.delete("ak_123")# Create an audience
audience = client.audiences.create({"name": "Newsletter"})
print(audience.id)
print(audience.token)
# List audiences
audiences = client.audiences.list()
# Get an audience
audience = client.audiences.get("aud_123")
# Update an audience
client.audiences.update("aud_123", {"name": "Updated Newsletter"})
# Delete an audience
client.audiences.delete("aud_123")Subscribers belong to an audience, so the audience ID is always the first argument.
# Add a subscriber
subscriber = client.subscribers.create("aud_123", {
"email": "user@example.com",
"first_name": "John",
"last_name": "Doe",
})
# List subscribers in an audience
subscribers = client.subscribers.list("aud_123")
# Get a subscriber
subscriber = client.subscribers.get("aud_123", "sub_456")
# Update a subscriber
client.subscribers.update("aud_123", "sub_456", {
"first_name": "Jane",
})
# Delete a subscriber
client.subscribers.delete("aud_123", "sub_456")# Create a template
result = client.templates.create({
"name": "Welcome",
"subject": "Welcome!",
"html": "<h1>Hi {{name}}</h1>",
})
# List templates
templates = client.templates.list()
# Get a template
template = client.templates.get("tem_123")
# Update a template
client.templates.update("tem_123", {"subject": "New Subject"})
# Publish a template
client.templates.publish("tem_123")
# Delete a template
client.templates.delete("tem_123")# Create a suppression
suppression = client.suppressions.create({
"email": "spam@example.com",
"type": "hard_bounce",
"reason": "Manual suppression",
})
# List suppressions
suppressions = client.suppressions.list()
# Get a suppression
suppression = client.suppressions.get("sup_123")
# Update a suppression
client.suppressions.update("sup_123", {"reason": "Updated"})
# Delete a suppression
client.suppressions.delete("sup_123")result = client.email_verifications.verify({
"email": "test@example.com",
})
print(result.status) # valid
print(result.score) # 0.95
print(result.risk) # low# Create a verification list
vlist = client.email_verification_lists.create({
"name": "Marketing List Q1",
"emails": [
"user1@example.com",
"user2@example.com",
"user3@example.com",
],
})
print(vlist.id) # evl_abc123...
print(vlist.status) # pending
# List all verification lists
vlists = client.email_verification_lists.list()
# Get a verification list
vlist = client.email_verification_lists.get("evl_abc123")
print(vlist.stats["successful_verifications"])
# Get verification results
results = client.email_verification_lists.results("evl_abc123", {"page": 1, "limit": 50})
for result in results:
print(f"{result.email} — {result.result}")
# Export results as XLSX
response = client.email_verification_lists.export("evl_abc123")
with open("results.xlsx", "wb") as f:
f.write(response.body.encode())# Create a webhook
webhook = client.webhooks.create({
"name": "My Webhook",
"url": "https://example.com/hook",
"all_events": True,
"enabled": True,
})
print(webhook.id)
# List webhooks
webhooks = client.webhooks.list()
# Get a webhook
webhook = client.webhooks.get("wh_123")
# Update a webhook
client.webhooks.update("wh_123", {"enabled": False})
# Delete a webhook
client.webhooks.delete("wh_123")# Create a contact
contact = client.contacts.create({
"email": "user@example.com",
"first_name": "John",
"last_name": "Doe",
})
print(contact.id)
# List contacts
contacts = client.contacts.list()
# Get a contact
contact = client.contacts.get("con_123")
# Update a contact
client.contacts.update("con_123", {"first_name": "Jane"})
# Delete a contact
client.contacts.delete("con_123")# List events
events = client.events.list({"type": "email.delivered"})
for event in events:
print(event.type)
# Get an event
event = client.events.get("evt_123")
print(event.type)
print(event.data["email_id"])The SDK provides typed event classes for all Emailit webhook event types under the emailit.events module, plus a WebhookSignature class for verifying webhook request signatures.
from emailit import WebhookSignature, ApiErrorException
from emailit.events import EmailDelivered
raw_body = request.body # raw request body string
signature = request.headers["x-emailit-signature"]
timestamp = request.headers["x-emailit-timestamp"]
secret = "your_webhook_signing_secret"
try:
event = WebhookSignature.verify(raw_body, signature, timestamp, secret)
# event is automatically typed based on the event type
print(event.type) # e.g. "email.delivered"
print(event.event_id) # e.g. "evt_abc123"
# Access the event data
data = event.get_event_data()
if isinstance(event, EmailDelivered):
# Handle delivered email
pass
except ApiErrorException as e:
return Response(e.args[0], status=401)You can disable replay protection by passing tolerance=None, or set a custom tolerance in seconds:
# Skip replay check
event = WebhookSignature.verify(raw_body, signature, timestamp, secret, tolerance=None)
# Custom 10-minute tolerance
event = WebhookSignature.verify(raw_body, signature, timestamp, secret, tolerance=600)Emails: email.accepted, email.scheduled, email.delivered, email.bounced, email.attempted, email.failed, email.rejected, email.suppressed, email.received, email.complained, email.clicked, email.loaded
Domains: domain.created, domain.updated, domain.deleted
Audiences: audience.created, audience.updated, audience.deleted
Subscribers: subscriber.created, subscriber.updated, subscriber.deleted
Contacts: contact.created, contact.updated, contact.deleted
Templates: template.created, template.updated, template.deleted
Suppressions: suppression.created, suppression.updated, suppression.deleted
Email Verifications: email_verification.created, email_verification.updated, email_verification.deleted
Email Verification Lists: email_verification_list.created, email_verification_list.updated, email_verification_list.deleted
Each event type has a corresponding class under emailit.events (e.g. EmailDelivered, DomainCreated). You can use isinstance checks or the EVENT_TYPE constant for routing:
from emailit.events import EmailDelivered, EmailBounced, ContactCreated
if isinstance(event, EmailDelivered):
handle_delivered(event)
elif isinstance(event, EmailBounced):
handle_bounce(event)
elif isinstance(event, ContactCreated):
handle_new_contact(event)
else:
print(f"Unhandled: {event.type}")The SDK raises typed exceptions for API errors:
from emailit import (
ApiErrorException,
AuthenticationException,
InvalidRequestException,
RateLimitException,
UnprocessableEntityException,
ApiConnectionException,
)
try:
client.emails.send({...})
except AuthenticationException:
# Invalid API key (401)
pass
except InvalidRequestException:
# Bad request or not found (400, 404)
pass
except RateLimitException:
# Too many requests (429)
pass
except UnprocessableEntityException:
# Validation failed (422)
pass
except ApiConnectionException:
# Network error
pass
except ApiErrorException as e:
# Any other API error
print(e.http_status)
print(e.http_body)
print(e.json_body)MIT -- see LICENSE for details.