Lists & Segments
SonarSend uses the same broad audience system for static lists and dynamic segments.
In the external API:
- lists are static segments
- segments are rule-based dynamic audiences
Both are referenced with friendly keys instead of raw UUIDs.
Public identifier#
Use:
segment_key
In broadcast payloads, use:
include_segment_keysexclude_segment_keys
Required scopes#
lists:readlists:writesegments:readsegments:write
The scope needed depends on whether the object is a static list or a dynamic segment.
List all visible audiences#
GET /api/segments
For API-key callers, SonarSend filters the response by the key’s scopes:
- a key with only
lists:readsees static lists - a key with only
segments:readsees dynamic segments - a key with both sees both
Get one list or segment#
GET /api/segments/:segment_key
Example:
GET /api/segments/vip-list
The response includes cached member counts and a count field for compatibility.
Create a dynamic segment#
POST /api/segments
A definition is a rule tree: a top-level { logic, conditions } where logic
is and or or, and each condition carries a type that selects its shape
(field, custom_field, event, subscription, segment, visit,
page_view, activity, or a nested group). It is recursive — a group
condition nests another { logic, conditions }.
Example — contacts who opened any email in the last 30 days:
{
"name": "Openers last 30 days",
"type": "dynamic",
"definition": {
"logic": "and",
"conditions": [
{
"type": "event",
"event_type": "email_opened",
"frequency": "exists",
"time_window": { "type": "relative", "direction": "within", "value": 30, "unit": "days" }
}
]
}
}
The definition is stored as sent and is not schema-validated on write, so a
malformed tree is accepted here but fails when the segment is evaluated. Build
it in the app once and copy the shape if you are unsure.
Required scope:
segments:write
Create a static list#
POST /api/segments
Example:
{
"name": "VIP List",
"type": "static"
}
Required scope:
lists:write
Update a list or segment#
PUT /api/segments/:segment_key
The allowed write scope depends on the target object:
- static list ->
lists:write - dynamic segment ->
segments:write
Refresh counts#
POST /api/segments/:segment_key/refresh-count
Use this when you want SonarSend to recompute cached counts for a dynamic audience.
Create a segment from broadcast engagement#
POST /api/segments/from-broadcast
Example:
{
"name": "Clicked April launch",
"broadcast_id": "8b11b2d7-e546-4a0f-a959-c7c7796fdb10",
"criterion": "clickers"
}
Returns the created segment, keyed by segment_key like every other segment
response — use it as the path parameter on the endpoints above.
Required scope:
segments:write
Static list member operations#
These endpoints only apply to static lists.
Add members#
POST /api/segments/:segment_key/members
Example:
{
"contact_ids": [
"2ec8d707-7b2d-451f-b5ec-e4f041d2b844",
"39de8127-0e65-4e72-b344-b9017608fe35"
]
}
Remove members#
DELETE /api/segments/:segment_key/members
List members#
GET /api/segments/:segment_key/members
Supported query parameters:
cursorlimitsearch
Required scopes:
lists:writefor add/removelists:readfor list members
List membership check#
POST /api/segments/membership-check
Example:
{
"contact_ids": [
"2ec8d707-7b2d-451f-b5ec-e4f041d2b844"
]
}
This returns each contact’s static list memberships using segment_key.
Integration guidance#
- Use segment keys in your own config instead of storing raw segment UUIDs.
- Use static lists when your integration owns exact membership.
- Use dynamic segments when SonarSend should evaluate rules over time.
- Keep list membership operations separate from dynamic segment management in your integration logic.