Python SDK

Official Python SDK for the Transactional Email, SMS, and Communication APIs.

The usetransactional Python SDK provides both synchronous and asynchronous clients for the Transactional API. Send emails, SMS messages, manage templates, suppressions, bounces, and more with full type hints and built-in error handling.

Installation

pip install usetransactional

Quick Start

from usetransactional import Transactional
 
client = Transactional(api_key="your-api-key")
 
response = client.emails.send(
    from_email="sender@yourdomain.com",
    to="recipient@example.com",
    subject="Hello from Transactional",
    html_body="<h1>Welcome!</h1><p>Thanks for signing up.</p>",
    text_body="Welcome! Thanks for signing up.",
)
 
print("Message ID:", response.message_id)

Configuration

client = Transactional(
    api_key="your-api-key",
    base_url="https://api.usetransactional.com",
    timeout=30,
    retries=3,
)
OptionTypeDefaultDescription
api_keystrrequiredYour Transactional API key
base_urlstrhttps://api.usetransactional.comAPI base URL (override for self-hosted or testing)
timeoutint30Request timeout in seconds
retriesint3Number of automatic retries on transient failures

Sync Client vs Async Client

The SDK provides two client classes. Use Transactional for synchronous code and AsyncTransactional for async/await workflows.

Sync Client

from usetransactional import Transactional
 
client = Transactional(api_key="your-api-key")
 
response = client.emails.send(
    from_email="sender@yourdomain.com",
    to="recipient@example.com",
    subject="Hello",
    html_body="<p>Hello, world!</p>",
)

Async Client

The async client uses a context manager to properly manage connections:

from usetransactional import AsyncTransactional
 
async def main():
    async with AsyncTransactional(api_key="your-api-key") as client:
        response = await client.emails.send(
            from_email="sender@yourdomain.com",
            to="recipient@example.com",
            subject="Hello",
            html_body="<p>Hello, world!</p>",
        )
        print("Message ID:", response.message_id)

Email

Send an Email

response = client.emails.send(
    from_email="sender@yourdomain.com",
    to="recipient@example.com",
    subject="Order Confirmation",
    html_body="<h1>Your order is confirmed</h1>",
    text_body="Your order is confirmed",
    tag="order-confirmation",
)

Send with a Template

response = client.emails.send_with_template(
    from_email="sender@yourdomain.com",
    to="recipient@example.com",
    template_alias="welcome-email",
    template_model={
        "name": "Alice",
        "company_name": "Acme Inc",
    },
)

Send Batch Emails

responses = client.emails.send_batch([
    {
        "from_email": "sender@yourdomain.com",
        "to": "alice@example.com",
        "subject": "Welcome, Alice!",
        "html_body": "<p>Welcome aboard, Alice.</p>",
        "tag": "welcome",
    },
    {
        "from_email": "sender@yourdomain.com",
        "to": "bob@example.com",
        "subject": "Welcome, Bob!",
        "html_body": "<p>Welcome aboard, Bob.</p>",
        "tag": "welcome",
    },
])

SMS

Send an SMS

response = client.sms.send(
    to="+15559876543",
    template_alias="verification-code",
    template_model={"code": "123456"},
)

Send Batch SMS

responses = client.sms.sendBatch([
    {
        "to": "+15559876543",
        "template_alias": "shipping-notification",
        "template_model": {"tracking_id": "TRK123"},
    },
    {
        "to": "+15551112222",
        "template_alias": "shipping-notification",
        "template_model": {"tracking_id": "TRK456"},
    },
])

Retrieve SMS Messages

# Get a specific SMS by ID
sms = client.sms.get("sms_abc123")
 
# List sent SMS messages
messages = client.sms.list()
 
# List inbound SMS messages (with optional count)
inbound = client.sms.list_inbound(count=50)

Templates

List Templates

templates = client.templates.list()
 
for template in templates:
    print(f"{template.id}: {template.name}")

Get a Template

template = client.templates.get(template_id="template_abc123")
print("Subject:", template.subject)
print("HTML:", template.html_body)

Create a Template

template = client.templates.create(
    name="Welcome Email",
    subject="Welcome to {{company_name}}",
    html_body="<h1>Welcome, {{name}}!</h1><p>Thanks for joining {{company_name}}.</p>",
)
 
print("Created template:", template.id)

Suppressions

Manage your suppression list to prevent sending to addresses that have opted out or bounced.

List Suppressions

suppressions = client.suppressions.list()
 
for entry in suppressions:
    print(f"{entry.email} - {entry.reason}")

Check an Email

result = client.suppressions.check("user@example.com")
print("Suppressed:", result.suppressed)

Add a Suppression

client.suppressions.add(
    email="user@example.com",
    reason="manual-suppression",
)

Remove a Suppression

client.suppressions.remove("user@example.com")

Bounces

List Bounces

bounces = client.bounces.list()
 
for bounce in bounces:
    print(f"{bounce.email} - {bounce.type} - {bounce.bounced_at}")

Get a Bounce

bounce = client.bounces.get(bounce_id="bounce_abc123")
print("Email:", bounce.email)
print("Type:", bounce.type)
print("Description:", bounce.description)

Reactivate a Bounced Email

If a bounce was transient, you can reactivate the email address for future sends:

client.bounces.activate("user@example.com")

Error Handling

The SDK raises specific exceptions for different failure modes. All error classes are available in transactional.errors:

from usetransactional import Transactional
from usetransactional.errors import (
    TransactionalError,
    AuthenticationError,
    RateLimitError,
    ValidationError,
    NotFoundError,
)
 
client = Transactional(api_key="your-api-key")
 
try:
    response = client.emails.send(
        from_email="sender@yourdomain.com",
        to="recipient@example.com",
        subject="Test",
        html_body="<p>Hello</p>",
    )
except AuthenticationError:
    print("Invalid API key. Check your credentials.")
except RateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after} seconds.")
except ValidationError as e:
    print(f"Invalid request: {e.message}")
except NotFoundError:
    print("Resource not found.")
except TransactionalError as e:
    print(f"API error: {e.message}")

Error Types

Error ClassDescription
TransactionalErrorBase error class for all SDK errors
AuthenticationErrorInvalid or missing API key (HTTP 401/403)
RateLimitErrorToo many requests; includes retry_after attribute (seconds)
ValidationErrorRequest payload failed validation (HTTP 422)
NotFoundErrorRequested resource does not exist (HTTP 404)

Async Support

For high-throughput applications or async frameworks like FastAPI, use the AsyncTransactional client with asyncio:

import asyncio
from usetransactional import AsyncTransactional
 
async def send_emails():
    async with AsyncTransactional(api_key="your-api-key") as client:
        # Send multiple emails concurrently
        tasks = [
            client.emails.send(
                from_email="sender@yourdomain.com",
                to=f"user{i}@example.com",
                subject=f"Notification #{i}",
                html_body=f"<p>Hello user {i}!</p>",
            )
            for i in range(10)
        ]
 
        results = await asyncio.gather(*tasks)
 
        for result in results:
            print(f"Sent: {result.message_id}")
 
asyncio.run(send_emails())

The async client supports all the same methods as the sync client, with await in front of each call. It uses async with as a context manager to properly open and close the underlying HTTP session.

Requirements

  • Python 3.8 or later