lettr.audience() service manages everything campaigns send to. Each kind is a sub-service:
Contacts
SUBSCRIBED, UNSUBSCRIBED, BOUNCED, COMPLAINED, UNVERIFIED.
API Reference
GET /audience/contacts
Double opt-in
Pass aDoubleOptInConfig to create the contact as unverified and send a confirmation email — they become subscribed after clicking the link:
Bulk create contacts
bulkCreate() takes up to 1000 contacts per request in one of two shapes. The flat emails shape gives every address the same lists, properties and topics:
contacts shape addresses each contact individually. Row-level listIds and topics are applied on top of the batch-wide ones, and a row’s properties key overrides the batch-wide value for that key:
emails or contacts, not both. For a row with no extra data, BulkAudienceContactRow.of("dan@example.com") is shorthand for the builder.
updateExisting defaults to false, which leaves existing contacts’ properties alone (they are still attached to the requested lists). Set it to true to merge properties — submitted keys overwrite, absent keys are preserved — and to let an opt-out drop an existing subscription.
Handling the result
getCode() returns the same value as a BulkAudienceContactErrorCode enum: missing_email, invalid_email, invalid_property_value, unknown_property_key, unknown_list, unknown_topic, or invalid_topic_subscription.
getAlreadyExisted() and getUpdated() overlap by design — “was the address already in the audience?” versus “did this request change the contact?” — so they don’t sum to the row count. A contact that already existed and got attached to a list is counted in both.Bulk membership
result.getContactIds() from a bulkCreate() feeds straight into the bulk membership calls, so no id lookup is needed in between:
contactIds × topicIds combination, up to 1000 contacts × 50 topics. Unsubscribing ignores pairs that don’t exist, so getUnsubscribed() can be lower than getTotalPairs().
API Reference
POST /audience/contacts/bulk
Lists
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. Build them withSegmentConditionsInput, SegmentConditionGroup, SegmentCondition, and the SegmentOperator enum.
API Reference
GET /audience/segments
Topics
API Reference
GET /audience/topics
Properties
Custom contact properties have an immutablename and type; only the fallback can be updated.
API Reference
GET /audience/properties
What’s Next
Campaigns
Send to your audience
API Reference
Full audience API reference