> ## 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.

# Audience

> Manage contacts, lists, subscription topics, custom properties, and dynamic segments with the Lettr Java SDK Audience service.

The `lettr.audience()` service manages everything campaigns send to. Each kind is a sub-service:

```java theme={null}
import com.lettr.Lettr;

Lettr lettr = new Lettr("your-api-key");

lettr.audience().contacts();    // individual contacts
lettr.audience().lists();       // contact lists
lettr.audience().topics();      // subscription topics
lettr.audience().properties();  // custom contact properties
lettr.audience().segments();    // dynamic segments
```

## Contacts

```java theme={null}
import com.lettr.services.audience.contacts.model.*;
import java.util.Map;

// Create (optionally attach to a list and set properties)
AudienceContactView contact = lettr.audience().contacts().create(
    CreateAudienceContactOptions.builder()
        .email("jane@example.com")
        .listId("list-uuid")
        .properties(Map.of("first_name", "Jane", "plan", "pro"))
        .build()
);
System.out.println(contact.getId() + " " + contact.getEmail() + " " + contact.getStatus());

// List with filters
ListAudienceContactsResponse page = lettr.audience().contacts().list(
    ListAudienceContactsParams.builder()
        .page(1)
        .perPage(50)
        .search("jane")
        .status(AudienceContactStatus.SUBSCRIBED)
        .listId("list-uuid")
        .build()
);

// Get, update, delete
lettr.audience().contacts().get("contact-uuid");
lettr.audience().contacts().update("contact-uuid",
    UpdateAudienceContactOptions.builder()
        .status(AudienceContactStatus.UNSUBSCRIBED)
        .properties(Map.of("plan", "enterprise"))
        .build()
);
lettr.audience().contacts().delete("contact-uuid");
```

Contact status values: `SUBSCRIBED`, `UNSUBSCRIBED`, `BOUNCED`, `COMPLAINED`, `UNVERIFIED`.

<Card title="API Reference" icon="book" href="/api-reference/audience/list-audience-contacts">
  GET /audience/contacts
</Card>

### Double opt-in

Pass a `DoubleOptInConfig` to create the contact as unverified and send a confirmation email — they become subscribed after clicking the link:

```java theme={null}
lettr.audience().contacts().create(
    CreateAudienceContactOptions.builder()
        .email("jane@example.com")
        .doubleOptIn(DoubleOptInConfig.builder()
            .from("hello@example.com")
            .subject("Confirm your subscription")
            .templateSlug("email-confirmation")
            .redirectUrl("https://example.com/confirmed")
            .build())
        .build()
);
```

### Bulk operations & membership

```java theme={null}
import java.util.List;

// Bulk create
lettr.audience().contacts().bulkCreate(
    BulkCreateAudienceContactsOptions.builder()
        .emails(List.of("a@example.com", "b@example.com"))
        .listId("list-uuid")
        .build()
);

// Single list / topic membership
lettr.audience().contacts().attachToList("contact-uuid", "list-uuid");
lettr.audience().contacts().detachFromList("contact-uuid", "list-uuid");
lettr.audience().contacts().subscribeToTopic("contact-uuid", "topic-uuid");
lettr.audience().contacts().unsubscribeFromTopic("contact-uuid", "topic-uuid");

// Bulk list membership (cartesian product of contactIds × listIds)
lettr.audience().contacts().bulkAttachToLists(
    BulkContactListsOptions.of(List.of("c1", "c2"), List.of("l1", "l2"))
);
lettr.audience().contacts().bulkDetachFromLists(
    BulkContactListsOptions.of(List.of("c1"), List.of("l1"))
);
```

## Lists

```java theme={null}
import com.lettr.services.audience.lists.model.*;

AudienceListView list = lettr.audience().lists().create(
    CreateAudienceListOptions.of("Newsletter")
);
System.out.println(list.getId() + " " + list.getName() + " " + list.getContactsCount());

lettr.audience().lists().get("list-uuid");
lettr.audience().lists().update("list-uuid",
    UpdateAudienceListOptions.builder().name("Weekly digest").build());
lettr.audience().lists().delete("list-uuid");

// Bulk delete
lettr.audience().lists().bulkDelete(
    BulkDeleteAudienceListsOptions.of(List.of("l1", "l2"))
);
```

<Card title="API Reference" icon="book" href="/api-reference/audience/list-audience-lists">
  GET /audience/lists
</Card>

## Segments

A segment is a dynamic group defined by conditions. Groups are joined by **OR**; conditions within a group by **AND**. Build them with `SegmentConditionsInput`, `SegmentConditionGroup`, `SegmentCondition`, and the `SegmentOperator` enum.

```java theme={null}
import com.lettr.services.audience.segments.model.*;

lettr.audience().segments().create(
    CreateAudienceSegmentOptions.builder()
        .name("Pro users at example.com")
        .listId("list-uuid")  // optional: restrict to one list
        .conditions(SegmentConditionsInput.of(
            SegmentConditionGroup.of(
                SegmentCondition.of("email", SegmentOperator.ENDS_WITH, "@example.com"),
                SegmentCondition.of("plan", SegmentOperator.EQUALS, "pro")
            )
        ))
        .build()
);

lettr.audience().segments().get("segment-uuid");
lettr.audience().segments().delete("segment-uuid");
```

<Card title="API Reference" icon="book" href="/api-reference/audience/list-audience-segments">
  GET /audience/segments
</Card>

## Topics

```java theme={null}
import com.lettr.services.audience.topics.model.*;

lettr.audience().topics().create(
    CreateAudienceTopicOptions.builder()
        .name("Product updates")
        .description("Occasional product news")
        .defaultSubscription(AudienceTopicDefaultSubscription.OPT_IN)  // immutable after creation
        .visibility(AudienceTopicVisibility.PUBLIC)
        .build()
);

lettr.audience().topics().get("topic-uuid");
lettr.audience().topics().delete("topic-uuid");
```

<Card title="API Reference" icon="book" href="/api-reference/audience/list-audience-topics">
  GET /audience/topics
</Card>

## Properties

Custom contact properties have an immutable `name` and `type`; only the fallback can be updated.

```java theme={null}
import com.lettr.services.audience.properties.model.*;

lettr.audience().properties().create(
    CreateAudiencePropertyOptions.builder()
        .name("plan")
        .type(AudiencePropertyType.STRING)  // STRING | NUMBER | BOOLEAN | DATE | JSON
        .fallbackValue("free")
        .build()
);

lettr.audience().properties().get("property-uuid");
lettr.audience().properties().delete("property-uuid");
```

<Card title="API Reference" icon="book" href="/api-reference/audience/list-audience-properties">
  GET /audience/properties
</Card>

## What's Next

<CardGroup cols={2}>
  <Card title="Campaigns" icon="paper-plane" href="/quickstart/java/campaigns">
    Send to your audience
  </Card>

  <Card title="API Reference" icon="book" href="/api-reference/audience/list-audience-lists">
    Full audience API reference
  </Card>
</CardGroup>
