---
"@context": https://schema.org
"@type": TechArticle
"@id": https://www.twilio.com/docs/cohorts/validating-cohort-criteria#article
headline: Validate cohort criteria with snapshots
description: Learn how to use Cohort Snapshots to preview a sample of matching profiles while you build your criteria, and to check whether a specific profile matches and why.
url: https://www.twilio.com/docs/cohorts/validating-cohort-criteria
inLanguage: en
dateModified: 2026-10-01T16:19:20.000Z
author:
  "@type": Organization
  name: Twilio Developer Education Team
publisher:
  "@type": Organization
  name: Twilio
---

# Validate cohort criteria with snapshots

## Two ways to validate criteria

Before you rely on a cohort's filter criteria, confirm that the filter captures the population you expect. You can verify this in two ways:

1. Preview a sample of matching profiles.
2. Check whether a specific profile that you expect to match (or not match) actually does.

You can do either task with a [snapshot](/docs/cohorts/concepts/snapshots). Because snapshots are immutable, point-in-time captures of matching profiles, you'll generate a new one each time you adjust the criteria as you validate.

## Preview your criteria against a sample of profiles

While you iterate on the criteria, generate a snapshot directly from your inline criteria with a small `profileLimit` to get quick feedback. Project the fields that the criteria reference so that you can confirm the filtering logic against real data.

```bash
curl -X POST 'https://audiences.twilio.com/preview/CohortSnapshots' \
-H 'Content-Type: application/json' \
-d '{
    "source": {
        "storeType": "TWILIO",
        "storeId": "mem_store_01h9d8r0vte3hz8tykdj329t7r",
        "criteria": "profile.trait.Account.status == \"active\" && profile.trait.Account.country == \"US\""
    },
    "profileLimit": 10,
    "variables": [
        { "expression": "profile.trait.Account.status", "displayName": "status" },
        { "expression": "profile.trait.Account.country", "displayName": "country" }
    ]
}' \
-u $TWILIO_API_KEY:$TWILIO_API_SECRET
```

After the operation completes, check the snapshot's `profileCount` to see the total number of matching profiles. Page through the sampled profiles to confirm that the projected values are as expected.

> \[!NOTE]
>
> Increase `profileLimit` for a larger sample, or omit the parameter to retrieve the full matching population. See [Retrieving profiles](/docs/cohorts/concepts/retrieving-profiles) for information about paging through large results.

## Check whether a specific profile matches

Sometimes a broad sample is not enough—you might need to confirm that a specific profile is correctly included or excluded.

Target the profile by its identifier. In the same request, project three things:

* The full criteria as a single Boolean (`overallMatch`).
* Each individual sub-condition as its own Boolean.
* The raw values behind them.

```bash
curl -X POST 'https://audiences.twilio.com/preview/CohortSnapshots' \
-H 'Content-Type: application/json' \
-d '{
    "source": {
        "storeType": "TWILIO",
        "storeId": "mem_store_01h9d8r0vte3hz8tykdj329t7r",
        "criteria": "\"jane@example.com\" in profile.address.email"
    },
    "variables": [
        { "expression": "profile.trait.Account.status == \"active\" && profile.trait.Account.country == \"US\"", "displayName": "overallMatch" },
        { "expression": "profile.trait.Account.status == \"active\"", "displayName": "statusActive" },
        { "expression": "profile.trait.Account.country == \"US\"", "displayName": "countryUs" },
        { "expression": "profile.trait.Account.status", "displayName": "statusValue" },
        { "expression": "profile.trait.Account.country", "displayName": "countryValue" }
    ]
}' \
-u $TWILIO_API_KEY:$TWILIO_API_SECRET
```

Interpret the result:

* **`profileCount` is `0`**: No profile in the store matches that identifier. Verify that you used the correct identifier and store; this isn't a criteria failure.
* **`profileCount` is `1` and `overallMatch` is `true`**: The profile matches the cohort's criteria.
* **`profileCount` is `1` and `overallMatch` is `false`**: The profile doesn't match.

In the example above, the per-condition Booleans (`statusActive`, `countryUs`) show how each clause evaluated, and the raw values (`statusValue`, `countryValue`) show the underlying data behind them. Together they explain why the profile did or did not match, regardless of whether `overallMatch` is `true` or `false`.

> \[!NOTE]
>
> Projecting each sub-condition as its own Boolean shows whether that piece matched, but it does not reveal how a mixed AND/OR expression combines them. For criteria such as `A && B || C`, which groups as `(A && B) || C` by [operator precedence](/docs/cohorts/cel/operators-and-precedence), you have two options:
>
> * Combine the leaf Booleans yourself in code based on that precedence.
> * Parse the criteria by the same precedence and project the grouped sub-expression—for example, `(A && B)`—so CEL evaluates that piece for you.

## Next steps

* Learn more about [Snapshots](/docs/cohorts/concepts/snapshots).
* See [example criteria](/docs/cohorts/cel/common-filtering-patterns) for common filtering patterns.
* Review [Using Cohorts with Bulk Messaging and Email](/docs/cohorts/bulk-messaging-and-email) for details on sending campaigns to a cohort.
