---
"@context": https://schema.org
"@type": TechArticle
"@id": https://www.twilio.com/docs/cohorts/concepts/snapshots#article
headline: Snapshots
description: Learn what a Snapshot is in Twilio Cohorts, how it materializes profiles that match your criteria, and how long its data is available.
url: https://www.twilio.com/docs/cohorts/concepts/snapshots
inLanguage: en
dateModified: 2026-10-01T16:19:20.000Z
author:
  "@type": Organization
  name: Twilio Developer Education Team
publisher:
  "@type": Organization
  name: Twilio
---

# Snapshots

## What is a snapshot

A snapshot is an immutable, point-in-time list of the profiles that match a set of filter criteria. When you create a snapshot, Cohorts evaluates the criteria against your connected profile store and materializes the matching profiles so you can retrieve them or pass them to downstream APIs.

Creating a snapshot starts an asynchronous [Operation](/docs/cohorts/concepts/operations). Poll the Operation until it completes, and then retrieve the snapshot's profiles.

## Two ways to create a snapshot

You can generate a snapshot in either of the following ways.

### From a saved cohort

Reference a cohort's ID in the `source` object. Cohorts resolves the cohort's saved criteria at the time you create the snapshot.

```bash
curl -X POST 'https://audiences.twilio.com/preview/CohortSnapshots' \
-H 'Content-Type: application/json' \
-d '{
    "source": {
        "cohortId": "cmp_cohort_01h9d8r0vte3hz8tykdj329t7r"
    },
    "labels": {
        "key": "value"
    }
}' \
-u $TWILIO_API_KEY:$TWILIO_API_SECRET
```

The optional `labels` object works the same way for either creation method described below.

### From inline criteria

Provide `storeType`, `storeId`, and `criteria` directly in the `source` object without saving a cohort first. Inline criteria are useful for ad-hoc audience checks, automated scripts, or exploratory testing.

```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\""
    }
}' \
-u $TWILIO_API_KEY:$TWILIO_API_SECRET
```

Regardless of the method you choose, the snapshot captures the criteria at the moment of creation. Later updates to a cohort's saved criteria do not alter existing snapshots.

## Idempotent retries

The Create Snapshot request accepts an optional `Idempotency-Key` header so you can safely retry a request without creating a duplicate snapshot. Generate a new key (for example, a UUID) for each distinct request, and reuse the same value only when retrying that exact request after a network failure or timeout. Idempotency keys are retained for at least 24 hours and are scoped to your account. A retry with the same key and an identical request body returns the original response, which includes an `Idempotent-Replayed: true` header. Reusing a key with a different request body fails with HTTP `422 Unprocessable Content`.

## Projecting data with variables

By default, a snapshot's profile results include only the profile ID. To include profile traits or address details in the response, pass a `variables` array when you create the snapshot. Each variable projects a specific field into the result set, keyed by `displayName`.

```json
"variables": [
  { "expression": "profile.address.email", "displayName": "email" },
  { "expression": "profile.trait.Account.firstName", "displayName": "firstName" }
]
```

A variable's `expression` can reference more than one trait or address field. It accepts any valid CEL expression, including arithmetic and string concatenation, for example:

```json
"variables": [
  { "expression": "profile.trait.Account.lifetimeValue - profile.trait.Account.totalRefunds", "displayName": "netValue" },
  { "expression": "profile.trait.Contact.firstName + \" \" + profile.trait.Contact.lastName", "displayName": "fullName" }
]
```

You can also use the ternary operator (`?:`) to derive a value from a condition, and chain multiple ternary expressions to handle more than two possible results. Each false branch becomes another ternary, so the expression continues evaluating conditions until one returns true or the final default branch executes.

For example, the following variable projects `"platinum"` when `lifetimeValue` is greater than 10,000, `"gold"` when it is greater than 1,000, and `"standard"` for all other values.

```json
"variables": [
  { "expression": "profile.trait.Account.lifetimeValue > 10000 ? \"platinum\" : profile.trait.Account.lifetimeValue > 1000 ? \"gold\" : \"standard\"", "displayName": "tier" }
]
```

See [Common filtering patterns](/docs/cohorts/cel/common-filtering-patterns) for more examples of valid CEL expressions.

You can project up to 50 variables in a single snapshot.

## Controlling snapshot size and scale

When you create a snapshot, you can pass optional parameters that control how the snapshot is computed and returned:

* **`profileLimit`** (integer, maximum 50): Sets a ceiling on the number of matching profiles included in the snapshot. Use this option for test sampling, quick previews, or to cap output size before you launch a full job.
* **`partitionCountOverride`** (integer, maximum 500): Manually sets the number of partitions generated for parallel fetching. If omitted, Cohorts calculates an optimal value based on your profile volume. When you specify a value, some partitions can be empty and return `"profiles": []`. For example, if you request 500 partitions and the snapshot contains 10 profiles, most partitions are empty. Learn more about [how partitions work and how to fetch them in parallel](/docs/cohorts/concepts/retrieving-profiles#large-snapshots-and-parallel-processing).

```bash
curl -X POST 'https://audiences.twilio.com/preview/CohortSnapshots' \
-H 'Content-Type: application/json' \
-d '{
    "source": {
        "cohortId": "cmp_cohort_01h9d8r0vte3hz8tykdj329t7r"
    },
    "profileLimit": 50,
    "partitionCountOverride": 4
}' \
-u $TWILIO_API_KEY:$TWILIO_API_SECRET
```

> \[!NOTE]
>
> When you validate or update cohort criteria, a common workflow is to check that your criteria capture the intended profiles. We recommend generating a snapshot with a small `profileLimit` (for example, `10`) and projecting:
>
> * Traits referenced in your criteria, such as `profile.trait.Account.status`, to confirm the filtering logic.
> * Address details, such as `profile.address.email` or `profile.address.phone`, to confirm which contact channels the matching profiles contain.
>
> The response also includes `profileCount`, which you can use to determine the total number of profiles that match your criteria.

## Profile data expiration

Profile data in a snapshot expires after a configurable period, set with `profilesExpiresAt` when you create the snapshot. The default is 7 days; you can extend this period to a maximum of 30 days. After the data expires, requests to list the snapshot's profiles return `404 Not Found`, but the snapshot's metadata, such as creation date and profile count, remains available.

## Deleting a snapshot

Deleting a snapshot is processed asynchronously and removes it entirely, including its metadata. In contrast, profile expiration only deletes the profile data and keeps the metadata.

## Next steps

* Learn about [Operations](/docs/cohorts/concepts/operations).
* Learn about [Retrieving profiles](/docs/cohorts/concepts/retrieving-profiles) from a snapshot.
* Learn about [Labels](/docs/cohorts/concepts/labels).
* See the [Cohorts API reference](/docs/api/audiences/preview).
