send0
SDK

Python SDK

Official Python SDK for send0 with sync and async support.

Installation

pip install send0

Requirements: Python >= 3.9

  • Powered by httpx for HTTP with connection pooling
  • Pydantic v2 models for type safety and validation
  • Both sync (Send0) and async (AsyncSend0) clients
  • Zero configuration — just pass your API key

Quick start

from send0 import Send0

client = Send0("sk_live_...")

# Send an email
email = client.emails.send(
    from_address="hello@yourdomain.com",
    to="user@example.com",
    subject="Welcome!",
    html="<p>Hello from send0</p>",
)

print(email.id)      # em_xxxx
print(email.status)  # 'queued'

Async support

from send0 import AsyncSend0

client = AsyncSend0("sk_live_...")

async def main():
    email = await client.emails.send(
        from_address="hello@yourdomain.com",
        to="user@example.com",
        subject="Welcome!",
        html="<p>Hello from send0</p>",
    )
    print(email.id)

    await client.close()

Context managers

Both clients support context managers for automatic cleanup:

# Sync
with Send0("sk_live_...") as client:
    email = client.emails.send(...)

# Async
async with AsyncSend0("sk_live_...") as client:
    email = await client.emails.send(...)

Available resources

ResourceDescription
client.emailsSend, get, list, batch, cancel emails
client.contactsCreate, update, list, delete contacts
client.templatesManage email templates
client.domainsDomain verification and management

Configuration

client = Send0(
    "sk_live_...",
    base_url="https://api.send0.dev/v1",  # Custom API URL
    timeout=60.0,                          # Request timeout in seconds
    max_retries=5,                         # Max retry attempts for 5xx
)
OptionTypeDefaultDescription
base_urlstrhttps://api.send0.dev/v1API base URL
timeoutfloat30.0Request timeout in seconds
max_retriesint3Max retry attempts for 5xx errors

Error handling

from send0 import Send0
from send0.errors import APIError, RateLimitError, ValidationError

client = Send0("sk_live_...")

try:
    email = client.emails.send(...)
except RateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after}s")
except APIError as e:
    print(f"{e.code}: {e.message} (HTTP {e.status_code})")

Error classes

ClassDescription
Send0ErrorBase class for all SDK errors
APIErrorAPI returned an error response (4xx/5xx)
RateLimitErrorRate limit exceeded (429)
NetworkErrorConnection or timeout error
ConfigErrorInvalid configuration (bad API key, etc.)
WebhookVerificationErrorWebhook signature verification failed

Webhook verification

from send0 import Webhooks

event = Webhooks.verify(
    payload=request.body,
    headers=request.headers,
    secret="whsec_...",
)

print(event["type"])  # "email.delivered"

Batch send

result = client.emails.batch(
    from_address="hello@acme.com",
    subject="Monthly Update",
    template="tmpl_monthly",
    recipients=[
        {"to": "jane@example.com", "variables": {"name": "Jane"}},
        {"to": "john@example.com", "variables": {"name": "John"}},
    ],
)

print(result.count)  # 2

Contacts

# Create
contact = client.contacts.create(
    email="jane@example.com",
    first_name="Jane",
    last_name="Doe",
    tags={"segment": "enterprise"},
)

# List
contacts = client.contacts.list(limit=50)
for c in contacts.data:
    print(c.email)

# Batch upsert
result = client.contacts.batch_upsert(contacts=[
    {"email": "jane@example.com", "first_name": "Jane"},
    {"email": "john@example.com", "first_name": "John"},
])

Templates

# Create
template = client.templates.create(
    name="welcome",
    subject="Welcome to {{company}}!",
    html="<h1>Welcome, {{name}}!</h1>",
)

# Preview
preview = client.templates.preview(
    template.id,
    data={"name": "Jane", "company": "Acme"},
)
print(preview.html)

Domains

# Add a domain
domain = client.domains.create(domain="mail.acme.com")

# Print DNS records to configure
for record in domain.dns_records:
    print(f"{record.type} {record.name}{record.value}")

# Verify after DNS configuration
result = client.domains.verify(domain.id)
print(result.status)  # 'verified'