---
"@context": https://schema.org
"@type": TechArticle
"@id": https://www.twilio.com/docs/bulk-messaging/cohorts#article
headline: Cohorts
description: Send Twilio Bulk Messaging campaigns to a Cohort, with per-Profile personalization and Cohort Snapshots for repeatable audiences.
url: https://www.twilio.com/docs/bulk-messaging/cohorts
inLanguage: en
dateModified: 2026-10-02T16:04:19.000Z
author:
  "@type": Organization
  name: Twilio Developer Education Team
publisher:
  "@type": Organization
  name: Twilio
---

# Cohorts

> \[!IMPORTANT]
>
> Twilio Cohorts is currently available as a Private Beta product and the information contained in this document is subject to change. You acknowledge and agree that your use of Twilio Cohorts is subject to the terms of the [Services in Private Beta](https://www.twilio.com/en-us/legal/service-country-specific-terms/private-beta). This means that some features are not yet implemented and others may be changed before the product is declared as Generally Available. Private Beta products are not covered by the Twilio Support Terms or Twilio Service Level Agreement.

> \[!IMPORTANT]
>
> Request access to the private beta through [this form](https://airtable.com/appRfMcPhtbqS6n2A/pagrrzSGrvqgGjjEu/form).

A **Cohort** is a Twilio-managed group of Profiles. Instead of listing every recipient by address, you reference the Cohort by its ID and Twilio fans the send out to every Profile in the group.

Use a Cohort when you want to:

* Maintain your audience as Profiles and let Twilio fan out sends on your behalf.
* Personalize each message with values sourced from a Profile's traits, without passing those values in your API request.

To create and manage Cohorts and Profiles, see the [Cohorts documentation](/docs/cohorts).

## Cohort vs. Cohort Snapshot

You can target a Cohort in two ways. Your choice determines when Twilio evaluates membership.

| Recipient shape    | ID prefix             | When membership is evaluated                                                                              |
| ------------------ | --------------------- | --------------------------------------------------------------------------------------------------------- |
| `cohortId`         | `cmp_cohort_`         | At send time. The message goes to every Profile currently in the Cohort.                                  |
| `cohortSnapshotId` | `cmp_cohortsnapshot_` | At snapshot time. The message goes to every Profile that was in the Cohort when the snapshot was created. |

Use a **Cohort** for live audiences that should reflect current membership on every send. Use a **Cohort Snapshot** when you need a frozen, repeatable audience, for example to resend the same campaign to the same recipients or to preserve an auditable record.

## Reference a Cohort in a Bulk Messaging request

The `to` array in a `POST /v1/Messages` request accepts a mix of recipient shapes. Two of them target Cohorts:

```json
{
  "to": [
    { "cohortId": "cmp_cohort_01h9krwprkeee8fzqspvwy6nq8" }
  ]
}
```

At send time, Twilio expands the Cohort recipient to every Profile in the Cohort. The 10,000-entry cap on `to` applies to array length, not to Cohort size — a Cohort can contain many more Profiles than that cap, governed by the Cohorts product.

A `cohortId` or `cohortSnapshotId` recipient must be the only entry in the `to` array. Mixing it with any other recipient, including another Cohort or Cohort Snapshot, returns `400`.

## Personalize messages per Profile

When the recipient is a Cohort, a Cohort Snapshot, or a Profile, the `variables` object supports two layers of templating: Cohort expressions resolve first, then Liquid renders the result into your content.

### Cohort expressions

Cohort expressions resolve values server-side, once per Profile. Wrap each expression in `${...}`. The expression body reads from the `profile.trait.<Group>.<field>` and `profile.address.<channel>` namespaces. For example:

* `${profile.trait.Contact.firstName}`
* `${profile.address.email}`

Whitespace inside the braces is optional and ignored, so `${ x }` and `${x}` are equivalent.

### Liquid rendering

After Twilio resolves the Cohort expressions to strings, it renders your `content` fields with Liquid. Reference each resolved value with `{{ variableName }}`. You can use any Liquid filter or control flow supported in a standard Bulk Messaging send. See [Personalization](/docs/bulk-messaging/personalization) for the full Liquid layer.

### Example: a Cohort recipient with per-Profile personalization

```json
{
  "to": [
    {
      "cohortId": "cmp_cohort_01h9krwprkeee8fzqspvwy6nq8",
      "variables": {
        "firstName": "${profile.trait.Contact.firstName}"
      }
    }
  ],
  "content": {
    "text": "Hello {{ firstName | default: 'Valued Customer' }}!"
  }
}
```

For each Profile in the Cohort, Twilio resolves `${profile.trait.Contact.firstName}` from that Profile's traits, then renders the `text` field with Liquid. If the trait is missing, the `default` filter falls back to `Valued Customer`.

## Limits and validation

The following limits apply to Cohort expressions in a request:

* Each `${...}` expression can contain at most 500 characters.
* A single recipient can reference at most 25 distinct `${...}` expressions across all of its `variables` values.
* A `variables` value can contain literal text and at most one `${...}` expression, for example `"Hi ${profile.trait.Contact.firstName}!"`. Two or more `${...}` expressions in the same value are rejected.

Twilio checks these rules synchronously when it receives your request. A violation returns `400 Bad Request`, and the send is never queued.

Twilio re-checks the semantic validity of a Cohort expression asynchronously while the Operation runs. This re-check is necessary because the referenced traits or [Twilio Memory Store](/docs/conversations/memory/memory-stores) may have changed after the Cohort was created. An invalid expression fails the Operation for the affected recipients, but does not fail the initial `POST /v1/Messages` request. Track the outcome using the Operation returned in the `202` response. See [Operations and Message Tracking](/docs/bulk-messaging/operations-and-message-tracking).

## Next steps

* Learn how to [send a message to a Cohort](/docs/bulk-messaging/send-to-a-cohort) end to end, with per-Profile personalization.
* See [Operations and Message Tracking](/docs/bulk-messaging/operations-and-message-tracking) to track the delivery status of your Cohort send.
