SDKs
Python SDK
Official Python SDK for the Sendr email API.
Installation
pip install sendr
# or with poetry
poetry add sendr
# or with uv
uv add sendr
Requires Python 3.9+.
Initialization
import sendr
# Simple initialization
client = sendr.Client(api_key="sndr_live_your_api_key")
# Or from environment variable
import os
client = sendr.Client(api_key=os.environ["SENDR_API_KEY"])
# With configuration
client = sendr.Client(
api_key=os.environ["SENDR_API_KEY"],
base_url="https://api.sendr.dev",
timeout=30, # seconds
max_retries=2,
)
Emails
# Send a single email
email = client.emails.send(
from_="Acme <hello@acme.com>",
to="user@example.com",
subject="Welcome!",
html="<h1>Welcome to Acme!</h1>",
)
print(email.id) # em_abc123
print(email.status) # queued
# Send to multiple recipients
client.emails.send(
from_="hello@acme.com",
to=["alice@example.com", "bob@example.com"],
subject="Team announcement",
html="<p>Big news...</p>",
)
# Send with attachment
import base64
with open("invoice.pdf", "rb") as f:
content = base64.b64encode(f.read()).decode()
client.emails.send(
from_="billing@acme.com",
to="user@example.com",
subject="Your invoice",
html="<p>Please find your invoice attached.</p>",
attachments=[
{
"filename": "invoice.pdf",
"content": content,
"content_type": "application/pdf",
}
],
)
# Send using a template
client.emails.send(
from_="hello@acme.com",
to="user@example.com",
template_id="tmpl_abc123",
variables={"name": "Alice", "plan": "Pro"},
)
# Batch send (up to 100 at once)
result = client.emails.send_batch(
from_="hello@acme.com",
subject="Order update",
emails=[
{"to": "alice@example.com", "html": "<p>Alice, your order shipped!</p>"},
{"to": "bob@example.com", "html": "<p>Bob, your order shipped!</p>"},
],
)
for item in result.data:
print(item.id, item.status)
# Get email status
email = client.emails.get("em_abc123")
print(email.status) # delivered
# List emails
page = client.emails.list(limit=25, status="delivered")
for email in page.data:
print(email.id, email.subject)
# Paginate
while page.has_more:
page = client.emails.list(cursor=page.next_cursor)
for email in page.data:
print(email.id)
# Cancel a scheduled email
client.emails.cancel("em_abc123")
Async support
import asyncio
import sendr
async def main():
client = sendr.AsyncClient(api_key=os.environ["SENDR_API_KEY"])
email = await client.emails.send(
from_="hello@acme.com",
to="user@example.com",
subject="Hello!",
html="<p>Async email!</p>",
)
print(email.id)
asyncio.run(main())
Domains
# Add a domain
domain = client.domains.create(name="acme.com")
for record in domain.dns_records:
print(f"{record.type} {record.host} → {record.value}")
# Verify after DNS propagation
result = client.domains.verify("dom_abc123")
print(result.status) # verified
client.domains.list()
client.domains.get("dom_abc123")
client.domains.remove("dom_abc123")
Error handling
from sendr.exceptions import (
ApiError,
AuthenticationError,
RateLimitError,
ValidationError,
)
import time
try:
client.emails.send(
from_="hello@acme.com",
to="user@example.com",
subject="Hello",
html="<p>Hi</p>",
)
except AuthenticationError:
print("Invalid API key — check SENDR_API_KEY")
except RateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after} seconds")
time.sleep(e.retry_after)
except ValidationError as e:
print("Validation failed:", e.details)
except ApiError as e:
print(f"API error {e.status_code}: {e.code} — {e.message}")
Context manager
with sendr.Client(api_key=os.environ["SENDR_API_KEY"]) as client:
email = client.emails.send(
from_="hello@acme.com",
to="user@example.com",
subject="Hello",
html="<p>Hi</p>",
)
# Connection pool closed on exit