Skip to main content
POST
Create a saved segment

Authorizations

X-API-Key
string
header
required

API key with format cs_live_xxx

Body

application/json

Create a saved segment.

The DB enforces that DYNAMIC carries a filter and STATIC does not (check_contact_lists_filter_matches_type); this mirrors it so the caller gets a 422 naming the field rather than a 500 from Postgres.

name
string
required
Required string length: 1 - 255
description
string | null
Maximum string length: 500
list_type
enum<string>
default:STATIC

Whether a contact list computes its members or stores them.

DYNAMIC lists evaluate contact_lists.filter_definition at query time and therefore pick up newly created contacts automatically. STATIC lists materialise membership rows in contact_list_members.

Available options:
DYNAMIC,
STATIC
filter_definition
ContactFilterSpec · object | null

The v1 directory filter set.

Deliberately a fixed, indexed set rather than a general boolean query builder: every field below resolves to an index on contacts or to an EXISTS over an indexed child, so a filter combination cannot degrade into a sequential scan of a team's directory.

Multiple fields AND together. Within a list-valued field the values OR together (signal=["HOT_LEAD","ENGAGED"] means either).

extra="forbid" is load-bearing. This model parses filter_definition JSONB written by earlier versions of the UI, and a silently-ignored unknown key would widen a saved segment instead of failing it -- which, for a list that feeds a campaign, means emailing people the segment was written to exclude.

Note there is no list_id field. Resolving a list is the service's job, precisely so a DYNAMIC list's filter cannot reference another list (or itself) and recurse.

contact_ids
string<uuid>[] | null

Initial members; STATIC lists only

Maximum array length: 1000

Response

List created

Response carrying a single saved segment.

message
string
required
contact_list
ContactListResponse · object
required

A saved segment.

success
boolean
default:true