Audience filters
Filter fields, preview counts, and when recipients are selected.
A saved audience is a named set of device filters. Use its ID as audience.audience_id
in a send request. To create one, follow target an audience.
The filters
An audience supports up to 20 filters. All filters must match (AND). An empty filter list matches every device in the app.
| Field | Shape | Matches |
|---|---|---|
platform | ios or android | Exactly |
push_permission | allowed, denied, provisional, undetermined | Exactly |
source | sdk or import | How the device arrived |
locale | A BCP 47 tag, fr-FR | Exactly, as reported |
timezone_id | An IANA identifier, Europe/Paris | Exactly |
app_version | 3.2.1 | Exactly |
app_build | 4821 | Exactly |
os_version | 18.2 | Exactly, as the vendor reported it |
last_active | within_days, 1 to 365 | Seen within that many days of the moment the audience resolves |
tag | key and value | The device's own tag, exactly |
For locale, timezone_id, app_version, app_build, os_version and tag,
choose exactly one comparison: value for equality, in for any value in a list,
or not_in to exclude the listed values. Lists contain 1–50 strings, each 1–256 characters.
Tag filters also support exists: true (key is present) or exists: false (key is absent).
Do not combine comparisons in the same filter. Filters still combine with AND.
{
"filters": [
{ "field": "locale", "in": ["fr-FR", "fr-CA"] },
{ "field": "tag", "key": "plan", "not_in": ["free"] },
{ "field": "tag", "key": "region", "exists": true }
]
}not_in matches devices without the tag
not_in matches every device whose value is not in the list, including devices that do not
carry the tag or field at all. { "field": "tag", "key": "plan", "not_in": ["free"] } matches
pro devices and devices that never set plan. in and value never match an absent tag.
An exclusion segment, "every country except these", therefore needs two filters on the same tag:
not_in for the excluded values and exists: true so devices that never set the tag stay out.
{
"filters": [
{ "field": "tag", "key": "country", "not_in": ["FR", "BE"] },
{ "field": "tag", "key": "country", "exists": true }
]
}Country and region are your own tags
Carillon does not infer a device's country from its locale, timezone or IP address. For country
or region targeting, set a tag from your own user record, such as country with an ISO 3166-1
alpha-2 code, with setTags() at sign-in and whenever the record changes. Your backend is the
source of that value, so the same code you use elsewhere is the one you filter on.
{
"name": "Active iOS",
"definition": {
"filters": [
{ "field": "platform", "value": "ios" },
{ "field": "last_active", "within_days": 30 },
{ "field": "tag", "key": "plan", "value": "pro" }
]
}
}This definition matches iOS devices active in the last 30 days with tags.plan equal to pro.
What reachable counts
POST /v1/apps/{appId}/audiences/preview returns the number of matching devices that are opted in
and not invalidated. It does not save the definition.
{ "reachable": 1284 }The count reflects current device state and can change before a send. A send also records failed deliveries for matching devices that are opted out or invalidated, so the campaign's total can exceed the reachable preview.
When recipients are selected
The campaign copies the audience's filters when the send request is accepted. Editing or deleting the saved audience afterwards does not change those copied filters.
Devices are selected when sending begins. For a scheduled campaign, devices registered later can match the copied filters when the campaign runs. For local-time schedules, selection happens per timezone wave.
Names and IDs
Names must be unique within an app. A duplicate name returns 409 duplicate_audience_name.
A send using an unknown audience ID, including one from another app, returns 422 unknown_audience.