Segments and targeting
Segments are reusable audience definitions. HoneyNotify evaluates their filter rules against enabled devices, user attributes, and recorded events.
Create a segment#
POST /v1/segments
{
"name": "Recently active paid iOS users",
"description": "Paid iOS users who opened a notification in the last 30 days",
"filter": {
"all": [
{"field": "platform", "operator": "eq", "value": "ios"},
{"field": "tag.plan", "operator": "eq", "value": "paid"},
{"field": "event.opened", "operator": "within_days", "value": 30}
]
}
}
{"segment_id":"a7f7b391-15e8-47b9-a123-f1bea3994a82","version":1}
Filter grammar#
A filter is either one condition or one group. A group contains a non-empty all or any array:
allrequires every child to match;anyrequires at least one child to match.
Groups can be nested up to five levels, with at most 50 leaf conditions total.
{
"any": [
{"field": "locale", "operator": "eq", "value": "en-GB"},
{
"all": [
{"field": "timezone", "operator": "eq", "value": "Europe/London"},
{"field": "tag.region", "operator": "eq", "value": "uk"}
]
}
]
}
Fields#
| Field | Source |
|---|---|
platform |
Device platform |
locale |
Device locale, falling back to user locale |
timezone |
Device timezone, falling back to user timezone |
app_version |
Registered app version |
enabled |
Device enabled state |
created_at |
Device creation time |
last_seen_at |
Device last-seen time |
tag.<key> |
Value from user tags |
event.<type> |
Standard event such as opened |
custom_event.<name> |
Named custom event |
Operators#
General fields accept eq, neq, in, not_in, contains, gt, gte, lt, lte, exists, and not_exists. The in and not_in operators accept between 1 and 100 values.
Event fields accept only exists, not_exists, within_days, and not_within_days. Day windows are integers from 0 to 3650.
Estimate before sending#
Estimate a saved segment:
POST /v1/segments/estimate
{"segment_id":"a7f7b391-15e8-47b9-a123-f1bea3994a82"}
Or estimate an unsaved filter:
{
"filter": {
"all": [
{"field": "platform", "operator": "eq", "value": "android"},
{"field": "tag.plan", "operator": "in", "value": ["pro", "unlimited"]}
]
}
}
The result is a point-in-time count of enabled, non-invalidated devices. Audience membership can change between estimation and send.
{"estimated_recipients":1842}
Versioning and snapshots#
Creating a segment starts at version 1. Each PATCH creates a new immutable version. When a notification is created, HoneyNotify snapshots the selected version and filter into the notification, so later segment edits do not rewrite the historical audience definition.
GET /v1/segments
GET /v1/segments/{segment_id}
PATCH /v1/segments/{segment_id}
DELETE /v1/segments/{segment_id}
Deleting archives the segment rather than erasing its history.
Include and exclude combinations#
Notification payloads may include up to 50 UUIDs in each of included_segment_ids and excluded_segment_ids. This is useful for rules such as “paid users, except anyone who purchased today.”
{
"title": "Complete your upgrade",
"body": "Your saved offer expires tonight.",
"target": {"type": "segment", "segment_id": "11111111-1111-4111-8111-111111111111"},
"included_segment_ids": ["11111111-1111-4111-8111-111111111111"],
"excluded_segment_ids": ["22222222-2222-4222-8222-222222222222"]
}
Every referenced segment is resolved and snapshotted when the notification is created. Use /segments/estimate for the primary filter and a controlled test audience before a large campaign.
