> ## 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 contact lists, contacts, subscription topics, custom properties, and dynamic segments with the Lettr Node.js SDK

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

```typescript theme={null}
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
```

All `list()` methods return paginated data with a `pagination` object (`total`, `per_page`, `current_page`, `last_page`).

## Contacts

```typescript theme={null}
import { Lettr } from "lettr";
const client = new Lettr(process.env.LETTR_API_KEY!);

// Create (optionally attach to a list and set properties)
const { data: contact } = await client.audience.contacts.create({
  email: "jane@example.com",
  list_id: "list-uuid",
  properties: { first_name: "Jane", plan: "pro" },
});

// List with filters
const { data, error } = await client.audience.contacts.list({
  page: 1,
  per_page: 50,
  search: "jane",
  status: "subscribed",
  list_id: "list-uuid",
});

if (!error) {
  for (const c of data.contacts) console.log(c.email, c.status);
  console.log(data.pagination.total);
}

// Get, update, delete
await client.audience.contacts.get("contact-uuid");
await client.audience.contacts.update("contact-uuid", {
  status: "unsubscribed",
  properties: { plan: "enterprise" },
});
await client.audience.contacts.delete("contact-uuid");
```

Contact `status` is `"subscribed"`, `"unsubscribed"`, `"bounced"`, `"complained"`, or `"unverified"`.

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

### Double opt-in

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

```typescript theme={null}
await 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

```typescript theme={null}
// Bulk create
await client.audience.contacts.bulkCreate({
  emails: ["a@example.com", "b@example.com"],
  list_id: "list-uuid",
});

// Single list / topic membership
await client.audience.contacts.attachList("contact-uuid", "list-uuid");
await client.audience.contacts.detachList("contact-uuid", "list-uuid");
await client.audience.contacts.subscribeTopic("contact-uuid", "topic-uuid");
await client.audience.contacts.unsubscribeTopic("contact-uuid", "topic-uuid");

// Bulk list membership
await client.audience.contacts.bulkAttachLists({
  contact_ids: ["c1", "c2"],
  list_ids: ["l1", "l2"],
});
await client.audience.contacts.bulkDetachLists({
  contact_ids: ["c1"],
  list_ids: ["l1"],
});
```

## Lists

```typescript theme={null}
const { data: list } = await client.audience.lists.create({ name: "Newsletter" });
console.log(list!.id, list!.name, list!.contacts_count);

await client.audience.lists.list({ page: 1, per_page: 20 });
await client.audience.lists.get("list-uuid");
await client.audience.lists.update("list-uuid", { name: "Weekly digest" });
await client.audience.lists.delete("list-uuid");

// Bulk delete
await client.audience.lists.bulkDelete({ list_ids: ["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**.

```typescript theme={null}
await 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" },
        ],
      },
    ],
  },
});

await client.audience.segments.list({ list_id: "list-uuid" });
await client.audience.segments.get("segment-uuid");
await client.audience.segments.delete("segment-uuid");
```

Operators include `equals`, `not_equals`, `contains`, `starts_with`, `ends_with`, `is_true`, `is_false`, and others.

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

## Topics

```typescript theme={null}
await 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"
});

await client.audience.topics.list({ per_page: 20 });
await client.audience.topics.get("topic-uuid");
await client.audience.topics.update("topic-uuid", { name: "Product news", visibility: "private" });
await client.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.

```typescript theme={null}
await client.audience.properties.create({
  name: "plan",
  type: "string",         // "string" | "number" | "boolean" | "date" | "json"
  fallback_value: "free",
});

await client.audience.properties.list({ page: 1 });
await client.audience.properties.get("property-uuid");
await client.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/nodejs/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>
