---
title: "Audiences"
description: "`audiences.list`, `get`, `create`, `update`, `delete`, `listContacts`, `addContact` and `removeContact`."
url: "https://openemail.uk/docs/sdk/audiences"
area: "SDK"
category: "Mailbox"
---

# Audiences

`audiences.list`, `get`, `create`, `update`, `delete`, `listContacts`, `addContact` and `removeContact`.

## Every method

**audiences.ts**

```
const audiences = await openemail.audiences.list()
const everyone = audiences.find((audience) => audience.builtin === 'default')

const list = await openemail.audiences.create({
  name: 'Product updates',
  description: 'Customers who asked to hear about releases',
})

await openemail.contacts.create({ email: 'grace@example.com', name: 'Grace Hopper' })
await openemail.audiences.addContact(list.id, { email: 'grace@example.com' })

const members = await openemail.audiences.listContacts(list.id, { limit: 200 })

await openemail.audiences.update(list.id, { name: 'Release notes' })
await openemail.audiences.removeContact(list.id, 'grace@example.com')
await openemail.audiences.delete(list.id)

console.log(everyone?.contactCount, members.length)
```

An audience is a named list of contacts in this workspace. Every contact is in the built-in default audience from the moment it exists, and `builtin` is what names that row; the rest are yours to make, fill and delete. Branch on `builtin` rather than on the name, which anybody can change.

This version manages lists and sends nothing to them. There is no broadcast method to go looking for, and putting a contact in an audience is a write to the audience rather than to the contact, so `audiences:write` is the only scope checked.

> `addContact` takes an address that is already a contact and refuses one that is not, with 422 `contact_not_found`. Save it with `openemail.contacts.create` first. Adding somebody twice answers with the membership that is already there, carrying its original `addedAt`, so the call is safe to retry.

> The default audience can be renamed and described like any other, but it cannot be deleted and it cannot be thinned. Both are refused with 409 `audience_immutable`. Delete the contact when you mean the contact to go.

## Response: AudienceResource

`list` resolves to a plain array of these, the default audience first and the rest newest first, and `get`, `create` and `update` each resolve to one. `listContacts` resolves to an array of `ContactResource` instead, the contacts themselves rather than membership records.

- `id` (string): The durable handle, `aud_` followed by 24 hex characters. Names are not unique, so this is what belongs in stored configuration.
- `name` (string): Trimmed on write, 1 to 120 characters. Two audiences may share a name, because an audience is addressed by its id.
- `description` (string | null): Free text for whoever reads the list later. Null when nobody wrote any, and an explicit null on `update` clears it.
- `builtin` ('default' | (string & {}) | null): `default` on exactly one row per workspace, the audience that holds every contact, and null on every audience somebody created. The union stays open so that a built-in added later narrows in an editor without breaking the published type.
- `contactCount` (number): How many contacts are in the audience, counted at the moment of the read rather than cached. Two reads either side of a `contacts.create` disagree by one.
- `createdAt` (string): ISO-8601 UTC, when the audience was made. Fixes the list order after the default one.
- `updatedAt` (string): ISO-8601 UTC, bumped by a rename or a description change. Membership changes do not touch it.
