Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.lettr.com/llms.txt

Use this file to discover all available pages before exploring further.

The client.audience resource manages everything campaigns send to. Each kind is a sub-resource:
import lettr

client = lettr.Lettr("lttr_your_api_key")

client.audience.contacts    # individual contacts
client.audience.lists       # contact lists
client.audience.topics      # subscription topics
client.audience.properties  # custom contact properties
client.audience.segments    # dynamic segments

Contacts

# Create (optionally attach to a list and set properties)
contact = client.audience.contacts.create(
    email="jane@example.com",
    list_id="list-uuid",
    properties={"first_name": "Jane", "plan": "pro"},
)
print(contact.id, contact.email, contact.status)

# List with filters
page = client.audience.contacts.list(
    page=1,
    per_page=50,
    search="jane",
    status="subscribed",
    list_id="list-uuid",
)
for c in page.contacts:
    print(c.email, c.status)

# Get, update, delete
client.audience.contacts.get("contact-uuid")
client.audience.contacts.update(
    "contact-uuid",
    status="unsubscribed",
    properties={"plan": "enterprise"},
)
client.audience.contacts.delete("contact-uuid")
Contact status is "subscribed", "unsubscribed", "bounced", "complained", or "unverified".

API Reference

GET /audience/contacts

Double opt-in

Pass a double_opt_in config to create the contact as unverified and send a confirmation email — they become subscribed after clicking the link:
client.audience.contacts.create(
    email="jane@example.com",
    double_opt_in={
        "from": "hello@example.com",
        "subject": "Confirm your subscription",
        "template_slug": "email-confirmation",
        "redirect_url": "https://example.com/confirmed",
    },
)

Bulk operations & membership

# Bulk create
client.audience.contacts.bulk_create(
    emails=["a@example.com", "b@example.com"],
    list_id="list-uuid",
)

# Single list / topic membership
client.audience.contacts.add_to_list(contact_id="contact-uuid", list_id="list-uuid")
client.audience.contacts.remove_from_list(contact_id="contact-uuid", list_id="list-uuid")
client.audience.contacts.subscribe_to_topic(contact_id="contact-uuid", topic_id="topic-uuid")
client.audience.contacts.unsubscribe_from_topic(contact_id="contact-uuid", topic_id="topic-uuid")

# Bulk list membership
client.audience.contacts.bulk_attach_lists(
    contact_ids=["c1", "c2"],
    list_ids=["l1", "l2"],
)
client.audience.contacts.bulk_detach_lists(contact_ids=["c1"], list_ids=["l1"])

Lists

audience_list = client.audience.lists.create(name="Newsletter")
print(audience_list.id, audience_list.name, audience_list.contacts_count)

client.audience.lists.list(page=1, per_page=20)
client.audience.lists.get("list-uuid")
client.audience.lists.update("list-uuid", name="Weekly digest")
client.audience.lists.delete("list-uuid")

# Bulk delete
client.audience.lists.bulk_delete(list_ids=["l1", "l2"])

API Reference

GET /audience/lists

Segments

A segment is a dynamic group defined by conditions. Groups are joined by OR; conditions within a group by AND. Conditions are a plain dict matching the API schema:
client.audience.segments.create(
    name="Pro users at example.com",
    list_id="list-uuid",  # optional: restrict to one list
    conditions={
        "groups": [
            {
                "conditions": [
                    {"field": "email", "operator": "ends_with", "value": "@example.com"},
                    {"field": "plan", "operator": "equals", "value": "pro"},
                ],
            },
        ],
    },
)

client.audience.segments.list(list_id="list-uuid")
client.audience.segments.get("segment-uuid")
client.audience.segments.delete("segment-uuid")
Operators include equals, not_equals, contains, starts_with, ends_with, is_true, is_false, and others.

API Reference

GET /audience/segments

Topics

client.audience.topics.create(
    name="Product updates",
    description="Occasional product news",
    default_subscription="opt_in",  # "opt_in" | "opt_out" — immutable after creation
    visibility="public",            # "public" | "private"
)

client.audience.topics.list(per_page=20)
client.audience.topics.get("topic-uuid")
client.audience.topics.update("topic-uuid", name="Product news", visibility="private")
client.audience.topics.delete("topic-uuid")

API Reference

GET /audience/topics

Properties

Custom contact properties have an immutable name and type; only the fallback can be updated.
client.audience.properties.create(
    name="plan",
    type="string",          # "string" | "number" | "boolean" | "date" | "json"
    fallback_value="free",
)

client.audience.properties.list(page=1)
client.audience.properties.get("property-uuid")
client.audience.properties.delete("property-uuid")

API Reference

GET /audience/properties

What’s Next

Campaigns

Send to your audience

API Reference

Full audience API reference