> ## Documentation Index
> Fetch the complete documentation index at: https://docs.letterby.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Audiences & Segmentation

> Complete guide to creating and managing audience segments for targeted campaigns and advanced contact filtering.

## Introduction to Audiences

Audiences allow you to segment your contacts into targeted groups for
personalized campaigns, analytics, and engagement strategies. Letterby supports
two types of audiences:

* **Manual Audiences**: Manually curated contact lists
* **Smart Audiences**: Dynamic segments that automatically update based on
  filter criteria

## Getting Started

### Prerequisites

Before working with audiences, ensure you have:

* A valid API key with access to your Letterby account
* At least one project (list) with contacts
* Understanding of your contact data structure

<Info>
  All audience endpoints require authentication via the `apiKey` header.
</Info>

## Creating Audiences

### Manual Audiences

Manual audiences are perfect for hand-picked segments like VIP customers or beta
testers.

<CodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://letterby.com/api/v4/audiences \
    --header 'Content-Type: application/json' \
    --header 'apiKey: YOUR_API_KEY' \
    --data '{
      "name": "VIP Customers",
      "listId": "your_list_id",
      "mode": "manual"
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://letterby.com/api/v4/audiences', {
  	method: 'POST',
  	headers: {
  		'Content-Type': 'application/json',
  		apiKey: 'YOUR_API_KEY',
  	},
  	body: JSON.stringify({
  		name: 'VIP Customers',
  		listId: 'your_list_id',
  		mode: 'manual',
  	}),
  })

  const audience = await response.json()
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://letterby.com/api/v4/audiences',
      headers={
          'Content-Type': 'application/json',
          'apiKey': 'YOUR_API_KEY'
      },
      json={
          'name': 'VIP Customers',
          'listId': 'your_list_id',
          'mode': 'manual'
      }
  )

  audience = response.json()
  ```
</CodeGroup>

### Smart Audiences

Smart audiences automatically include contacts based on filter criteria. They
update in real-time as your contact data changes.

<CodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://letterby.com/api/v4/audiences \
    --header 'Content-Type: application/json' \
    --header 'apiKey: YOUR_API_KEY' \
    --data '{
      "name": "High-Value Contacts",
      "listId": "your_list_id",
      "mode": "smart",
      "filters": "{\"points\": {\"gte\": 100}, \"isVerified\": true}"
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch('https://letterby.com/api/v4/audiences', {
  	method: 'POST',
  	headers: {
  		'Content-Type': 'application/json',
  		apiKey: 'YOUR_API_KEY',
  	},
  	body: JSON.stringify({
  		name: 'High-Value Contacts',
  		listId: 'your_list_id',
  		mode: 'smart',
  		filters: JSON.stringify({
  			points: { gte: 100 },
  			isVerified: true,
  		}),
  	}),
  })
  ```

  ```python Python theme={null}
  import json
  import requests

  filters = {
      "points": {"gte": 100},
      "isVerified": True
  }

  response = requests.post(
      'https://letterby.com/api/v4/audiences',
      headers={
          'Content-Type': 'application/json',
          'apiKey': 'YOUR_API_KEY'
      },
      json={
          'name': 'High-Value Contacts',
          'listId': 'your_list_id',
          'mode': 'smart',
          'filters': json.dumps(filters)
      }
  )
  ```
</CodeGroup>

## Advanced Filtering for Smart Audiences

Smart audiences use Prisma-compatible where clauses, allowing for complex
filtering logic.

### Basic Filtering Examples

#### By Points Range

```json theme={null}
{
	"filters": "{\"points\": {\"gte\": 50, \"lte\": 200}}"
}
```

#### By Email Domain

```json theme={null}
{
	"filters": "{\"email\": {\"contains\": \"@gmail.com\"}}"
}
```

#### By Verification Status

```json theme={null}
{
	"filters": "{\"isVerified\": true, \"unsubscribed\": false}"
}
```

### Complex Filtering with AND/OR Logic

#### Gmail Users with High Points

```json theme={null}
{
	"filters": "{\"AND\": [{\"email\": {\"contains\": \"@gmail.com\"}}, {\"points\": {\"gt\": 100}}]}"
}
```

#### Multiple Conditions with OR

```json theme={null}
{
	"filters": "{\"OR\": [{\"points\": {\"gte\": 200}}, {\"referrals\": {\"gte\": 5}}]}"
}
```

#### Complex Nested Logic

```json theme={null}
{
	"filters": "{\"AND\": [{\"isVerified\": true}, {\"OR\": [{\"points\": {\"gte\": 100}}, {\"company\": {\"in\": [\"Google\", \"Apple\", \"Microsoft\"]}}]}]}"
}
```

### Available Filter Fields

| Field          | Type    | Description             | Example                               |
| -------------- | ------- | ----------------------- | ------------------------------------- |
| `email`        | String  | Contact's email address | `{"contains": "@company.com"}`        |
| `firstName`    | String  | First name              | `{"startsWith": "John"}`              |
| `lastName`     | String  | Last name               | `{"endsWith": "Smith"}`               |
| `points`       | Number  | Points accumulated      | `{"gte": 100}`                        |
| `referrals`    | Number  | Number of referrals     | `{"gt": 5}`                           |
| `isVerified`   | Boolean | Verification status     | `true`                                |
| `unsubscribed` | Boolean | Subscription status     | `false`                               |
| `company`      | String  | Company name            | `{"in": ["Tech Corp", "StartupXYZ"]}` |
| `country`      | String  | Country                 | `{"equals": "United States"}`         |
| `city`         | String  | City                    | `{"contains": "New York"}`            |
| `createdAt`    | Date    | Registration date       | `{"gte": "2024-01-01T00:00:00Z"}`     |

### String Operators

* `equals`: Exact match
* `contains`: Partial match (case-insensitive)
* `startsWith`: Starts with text
* `endsWith`: Ends with text
* `in`: Matches any value in array
* `notIn`: Doesn't match any value in array

### Number Operators

* `equals`: Exact value
* `gt`: Greater than
* `gte`: Greater than or equal
* `lt`: Less than
* `lte`: Less than or equal
* `in`: Matches any value in array

## Managing Audiences

### Listing All Audiences

Retrieve all audiences for a specific list:

<CodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url 'https://letterby.com/api/v4/audiences?listId=your_list_id' \
    --header 'apiKey: YOUR_API_KEY'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch(
  	'https://letterby.com/api/v4/audiences?listId=your_list_id',
  	{
  		headers: {
  			apiKey: 'YOUR_API_KEY',
  		},
  	},
  )

  const { data } = await response.json()
  console.log(data.audiences)
  ```
</CodeGroup>

### Retrieving a Specific Audience

Get detailed information about a single audience:

<CodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url https://letterby.com/api/v4/audiences/audience_id \
    --header 'apiKey: YOUR_API_KEY'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch(
  	'https://letterby.com/api/v4/audiences/audience_id',
  	{
  		headers: {
  			apiKey: 'YOUR_API_KEY',
  		},
  	},
  )

  const { data } = await response.json()
  console.log(data.audience.subs) // View contacts in audience
  ```
</CodeGroup>

### Updating Audiences

Modify audience properties including name, filters, and mode:

<CodeGroup>
  ```bash cURL theme={null}
  curl --request PATCH \
    --url https://letterby.com/api/v4/audiences/audience_id \
    --header 'Content-Type: application/json' \
    --header 'apiKey: YOUR_API_KEY' \
    --data '{
      "name": "Updated Audience Name",
      "filters": "{\"points\": {\"gte\": 150}}"
    }'
  ```

  ```javascript Node.js theme={null}
  const response = await fetch(
  	'https://letterby.com/api/v4/audiences/audience_id',
  	{
  		method: 'PATCH',
  		headers: {
  			'Content-Type': 'application/json',
  			apiKey: 'YOUR_API_KEY',
  		},
  		body: JSON.stringify({
  			name: 'Updated Audience Name',
  			filters: JSON.stringify({
  				points: { gte: 150 },
  			}),
  		}),
  	},
  )
  ```
</CodeGroup>

## Practical Use Cases

### 1. Customer Lifecycle Segmentation

```javascript theme={null}
// New subscribers (less than 30 days)
const newSubscribers = {
	name: 'New Subscribers',
	mode: 'smart',
	filters: JSON.stringify({
		createdAt: {
			gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString(),
		},
	}),
}

// Engaged users (high points)
const engagedUsers = {
	name: 'Engaged Users',
	mode: 'smart',
	filters: JSON.stringify({
		points: { gte: 50 },
		isVerified: true,
	}),
}

// At-risk users (no recent activity)
const atRiskUsers = {
	name: 'At-Risk Users',
	mode: 'smart',
	filters: JSON.stringify({
		points: { lt: 10 },
		createdAt: {
			lte: new Date(Date.now() - 60 * 24 * 60 * 60 * 1000).toISOString(),
		},
	}),
}
```

### 2. Geographic Targeting

```javascript theme={null}
// US-based enterprise contacts
const usEnterprise = {
	name: 'US Enterprise',
	mode: 'smart',
	filters: JSON.stringify({
		AND: [
			{ country: { equals: 'United States' } },
			{ company: { not: null } },
			{ points: { gte: 25 } },
		],
	}),
}
```

### 3. Referral Champions

```javascript theme={null}
// Top referrers
const referralChampions = {
	name: 'Referral Champions',
	mode: 'smart',
	filters: JSON.stringify({
		referrals: { gte: 3 },
	}),
}
```

## Best Practices

### 1. Naming Conventions

* Use descriptive names: "High-Value Gmail Users" vs "Audience 1"
* Include criteria in the name when helpful
* Use consistent naming patterns across your organization

### 2. Filter Optimization

* Start with simple filters and gradually add complexity
* Test filters with small datasets first
* Use specific date ranges to avoid overly large audiences

### 3. Regular Maintenance

* Review audience performance regularly
* Update filter criteria based on changing business needs
* Archive unused audiences to keep your workspace clean

### 4. Testing Smart Audiences

```javascript theme={null}
// Test your filters before creating the audience
const testFilters = {
	points: { gte: 100 },
	isVerified: true,
}

// First, test with the contacts endpoint
const testResponse = await fetch(
	`https://letterby.com/api/v4/contacts?listId=your_list_id&points=100&isVerified=true`,
	{
		headers: { apiKey: 'YOUR_API_KEY' },
	},
)

const testResults = await testResponse.json()
console.log(`Filter would match ${testResults.data.pagination.total} contacts`)
```

## Error Handling

### Common Errors and Solutions

#### Invalid Filters Format

```json theme={null}
{
	"error": "Invalid filters format. Must be a valid Prisma where clause for Sub model"
}
```

**Solution**: Ensure your filters follow Prisma where clause syntax and are
valid JSON.

#### Missing Required Fields

```json theme={null}
{
	"error": "Name and listId are required"
}
```

**Solution**: Always include `name` and `listId` when creating audiences.

#### Filters Required for Smart Mode

```json theme={null}
{
	"error": "Filters are required for smart mode"
}
```

**Solution**: Smart audiences must include a `filters` parameter.

## API Reference Links

For detailed endpoint documentation, see:

* [Create Audience](/api-reference/endpoint/audience-create)
* [List Audiences](/api-reference/endpoint/audiences-list)
* [Get Audience](/api-reference/endpoint/audience-retrieve)
* [Update Audience](/api-reference/endpoint/audience-update)
* [Delete Audience](/api-reference/endpoint/audience-delete)

## Next Steps

Once you've mastered audiences, explore:

* Using audiences in email campaigns
* Analyzing audience engagement metrics
* Building automated workflows based on audience membership
* Integrating audiences with your CRM or marketing tools

<Tip>
  Smart audiences update automatically, so contacts will move in and out based
  on their current data. This makes them perfect for dynamic marketing campaigns
  and automated workflows.
</Tip>
