Segments
A segment is a saved set of conditions, such as "iOS users who bought pro_yearly in the last 90 days". Use it as the audience of a server push, an in-app message or a journey. The concepts are in the Segments guide.
These endpoints live on the SDK host: https://sdk.sqd.link on grovs Cloud, https://sdk.<SERVER_HOST> when you self-host. Send your project key in the PROJECT-KEY header. Send production or test in the ENVIRONMENT header. Each environment has its own segments.
Availability: an active paid plan on grovs Cloud. Always on for self-hosted Enterprise. Without it, every call answers 403 with error_code: "enterprise_required". Estimates, counts and identifier lists need ClickHouse.
Rate limit: 120 requests a minute per project key, shared with in-app messages. Over it, the answer is 429 with error_code: "rate_limited" and a Retry-After header.
Dashboard only: the member list, breakdowns, CSV exports, size history and the identifier list preview and download.
IDs: segment IDs are hashids, such as gk3x.
The segment object
idstringHashid of the segment.
namestringUp to 255 characters.
descriptionstring | nullFree text.
definitionobjectThe conditions, in canonical form: keys sorted and defaults filled in. See The definition.
definition_hashstringDigest of the canonical definition. It changes when the definition does.
archivedbooleanArchived segments are not evaluated and cannot be targeted.
has_identifier_listbooleantrue once an identifier list was uploaded.
identifier_listobject | nullcount and updated_at of the uploaded list. null without one.
sizeobject | nullThe latest daily size snapshot for the current definition: date, persons, devices. null when there is none from the last 7 days, such as for a new or just edited segment.
created_atstringISO 8601.
updated_atstringISO 8601.
{
"id": "gk3x",
"name": "iOS pro buyers",
"description": "Bought pro_yearly in the last 90 days",
"definition": {
"version": 1,
"operator": "and",
"groups": [
{
"operator": "and",
"conditions": [
{ "type": "device", "field": "platform", "op": "is", "value": ["ios"], "mode": "current" },
{ "type": "purchase", "product_id": ["pro_yearly"], "count": 1, "window": { "last_days": 90 } }
]
}
]
},
"definition_hash": "a1b2c3d4…",
"archived": false,
"has_identifier_list": false,
"identifier_list": null,
"size": { "date": "2026-10-21", "persons": 4821, "devices": 5310 },
"created_at": "2026-10-01T10:00:00.000Z",
"updated_at": "2026-10-21T04:00:12.000Z"
}The definition
A definition has two levels. Conditions sit inside groups, and each group's operator (and or or) combines its conditions. The top-level operator combines the groups. Groups cannot be nested.
versionintegerRequiredAlways 1.
operatorenumRequiredand or or. Combines the groups.
groupsarrayRequired1 to 5 groups. Each has an operator and 1 to 10 conditions.
Each condition has a type and fields that depend on it. Every field, operator and example is in Condition types.
type | Matches | Key fields |
|---|---|---|
event | A built-in event, a custom event, or any activity | One of event_type, event_name, any: true. count, window, filters, negate |
device | Device and app fields | field, op, value, mode (current or used with a window) |
profile | A property your app set on the user | field (properties.<key>), op, value |
first_seen | When the person first appeared | op (gte or lte), value (a date) |
identifier | Your own user ID, or the uploaded list | op (is, contains, is_set, is_not_set, in_list, not_in_list), value |
acquisition | The install or reinstall that brought the person in | field (link_id, campaign_id, tracking_source, tracking_medium), op, value, window |
purchase | In-app purchases and subscriptions | product_id, purchase_type, store_source, count, min_total_usd_cents, window, negate |
A window is { "last_days": N } or { "from": "YYYY-MM-DD", "to": "YYYY-MM-DD" }, in UTC and whole days.
A "did not" condition (negate, is_not, is_not_set, not_in_list) must sit in an and group with a positive one.
| Limit | Value |
|---|---|
| Groups per definition | 5 |
| Conditions per group | 10 |
Filters per event condition | 25 |
| Values per condition or filter | 100 |
| Value length | 256 bytes |
| Identifiers per uploaded list | 200,000 |
event and device windows | 90 days |
acquisition and purchase windows | 365 days |
purchase conditions need revenue tracking. Read the limits your install runs with from the condition catalogue.
{
"version": 1,
"operator": "or",
"groups": [
{
"operator": "and",
"conditions": [
{ "type": "event", "event_type": "app_open", "window": { "last_days": 30 } },
{ "type": "event", "event_name": "checkout", "negate": true, "window": { "last_days": 30 } }
]
},
{
"operator": "and",
"conditions": [
{ "type": "identifier", "op": "in_list" }
]
}
]
}List segments
/api /v1 /sdk /server /segmentsReturns up to 200 segments of the environment, most recently updated first.
PROJECT-KEYstringRequiredYour project key.
ENVIRONMENTstringRequiredproduction or test.
archivedbooleantrue lists archived segments instead of active ones. Default false.
Returns 200 with segments, a list of segment objects, and truncated: true when there are more than 200.
Errors
curl -X GET "https://sdk.sqd.link/api/v1/sdk/server/segments" \
-H "PROJECT-KEY: $GROVS_PROJECT_KEY" \
-H "ENVIRONMENT: production"{
"segments": [
{
"id": "gk3x",
"name": "iOS pro buyers",
"description": null,
"definition": { "version": 1, "operator": "and", "groups": ["…"] },
"definition_hash": "a1b2c3d4…",
"archived": false,
"has_identifier_list": false,
"identifier_list": null,
"size": { "date": "2026-10-21", "persons": 4821, "devices": 5310 },
"created_at": "2026-10-01T10:00:00.000Z",
"updated_at": "2026-10-21T04:00:12.000Z"
}
],
"truncated": false
}Get the condition catalogue
/api /v1 /sdk /server /segments /fieldsReturns every condition type with its fields, operators and window caps, plus the limits this install runs with. Use it to build or validate definitions.
PROJECT-KEYstringRequiredYour project key.
ENVIRONMENTstringRequiredproduction or test.
Returns 200 with version, limits and conditions. profile lists up to 200 property_keys seen on your users. purchase has enabled: false while revenue tracking is off.
Errors
curl -X GET "https://sdk.sqd.link/api/v1/sdk/server/segments/fields" \
-H "PROJECT-KEY: $GROVS_PROJECT_KEY" \
-H "ENVIRONMENT: production"{
"version": 1,
"limits": {
"groups": 5,
"conditions_per_group": 10,
"filters": 25,
"values": 100,
"value_bytes": 256,
"identifier_list": 200000
},
"conditions": [
{
"type": "event",
"event_types": ["app_open", "view", "open", "install", "…"],
"filter_columns": ["screen_name", "platform", "app_version", "…"],
"filter_ops": ["is", "is_not", "contains"],
"property_prefix": "properties.",
"max_window_days": 90,
"negatable": true
},
{ "type": "profile", "ops": ["is", "is_not", "contains", "is_set", "is_not_set"], "property_prefix": "properties.", "property_keys": ["plan", "clinic_id"] },
{ "type": "purchase", "enabled": true, "purchase_types": ["subscription", "one_time"], "max_window_days": 365, "negatable": true },
"…"
]
}Estimate a segment
/api /v1 /sdk /server /segments /estimateCounts the people and devices a definition matches without saving it. Send a draft definition, a saved segment_id, or both to estimate an edit of that segment against its uploaded identifier list.
PROJECT-KEYstringRequiredYour project key.
ENVIRONMENTstringRequiredproduction or test.
definitionobjectA definition. Required without segment_id.
segment_idstringAn active segment. Alone, it estimates that segment. With definition, its identifier list backs the draft's in_list and not_in_list.
Returns 200 with persons, devices, approximate (always false: counts are exact) and incomplete. incomplete is true when a window reaches past your data retention, so the count may be low.
Errors
curl -X POST "https://sdk.sqd.link/api/v1/sdk/server/segments/estimate" \
-H "PROJECT-KEY: $GROVS_PROJECT_KEY" \
-H "ENVIRONMENT: production" \
-H "Content-Type: application/json" \
-d '{
"definition": {
"version": 1,
"operator": "or",
"groups": [
{
"operator": "and",
"conditions": [
{
"type": "event",
"event_name": "checkout",
"window": { "last_days": 30 }
}
]
}
]
}
}'{
"persons": 1204,
"devices": 1388,
"approximate": false,
"incomplete": false
}{
"error": "groups: between 1 and 5 groups are required"
}Create a segment
/api /v1 /sdk /server /segmentsSaves a segment. The definition is validated and stored in canonical form.
PROJECT-KEYstringRequiredYour project key.
ENVIRONMENTstringRequiredproduction or test.
namestringRequiredUp to 255 characters.
definitionobjectRequiredA definition. A fixed window that starts before your data retention cutoff is refused.
descriptionstringFree text.
Returns 201 with segment, a segment object.
Errors
curl -X POST "https://sdk.sqd.link/api/v1/sdk/server/segments" \
-H "PROJECT-KEY: $GROVS_PROJECT_KEY" \
-H "ENVIRONMENT: production" \
-H "Content-Type: application/json" \
-d '{
"name": "iOS pro buyers",
"description": "Bought pro_yearly in the last 90 days",
"definition": {
"version": 1,
"operator": "and",
"groups": [
{
"operator": "and",
"conditions": [
{
"type": "device",
"field": "platform",
"op": "is",
"value": ["ios"],
"mode": "current"
},
{
"type": "purchase",
"product_id": ["pro_yearly"],
"window": { "last_days": 90 }
}
]
}
]
}
}'{
"segment": {
"id": "gk3x",
"name": "iOS pro buyers",
"description": "Bought pro_yearly in the last 90 days",
"definition": { "version": 1, "operator": "and", "groups": ["…"] },
"definition_hash": "a1b2c3d4…",
"archived": false,
"has_identifier_list": false,
"identifier_list": null,
"size": null,
"created_at": "2026-10-22T09:00:00.000Z",
"updated_at": "2026-10-22T09:00:00.000Z"
}
}{
"error": "Definition groups[0].conditions[0]: type must be one of event, device, profile, first_seen, identifier, acquisition, purchase"
}Retrieve a segment
/api /v1 /sdk /server /segments /{segment_id}Returns one segment, archived or not.
PROJECT-KEYstringRequiredYour project key.
ENVIRONMENTstringRequiredproduction or test.
segment_idstringRequiredThe segment's id.
Returns 200 with segment, a segment object.
Errors
curl -X GET "https://sdk.sqd.link/api/v1/sdk/server/segments/{segment_id}" \
-H "PROJECT-KEY: $GROVS_PROJECT_KEY" \
-H "ENVIRONMENT: production"{
"segment": {
"id": "gk3x",
"name": "iOS pro buyers",
"archived": false,
"size": { "date": "2026-10-21", "persons": 4821, "devices": 5310 },
"…": "…"
}
}{
"error": "Segment not found"
}Update a segment
/api /v1 /sdk /server /segments /{segment_id}Changes only the fields you send. A new definition gets a new definition_hash and starts a fresh size history. Campaigns already launched on the segment keep the audience they froze at launch.
PROJECT-KEYstringRequiredYour project key.
ENVIRONMENTstringRequiredproduction or test.
segment_idstringRequiredThe segment's id.
namestringUp to 255 characters.
descriptionstring | nullFree text.
definitionobjectA full definition. It replaces the old one.
archivedbooleanfalse restores an archived segment.
Returns 200 with segment, a segment object.
Errors
curl -X PATCH "https://sdk.sqd.link/api/v1/sdk/server/segments/{segment_id}" \
-H "PROJECT-KEY: $GROVS_PROJECT_KEY" \
-H "ENVIRONMENT: production" \
-H "Content-Type: application/json" \
-d '{
"name": "iOS pro buyers, 30 days",
"definition": {
"version": 1,
"operator": "and",
"groups": [
{
"operator": "and",
"conditions": [
{
"type": "device",
"field": "platform",
"op": "is",
"value": ["ios"],
"mode": "current"
},
{
"type": "purchase",
"product_id": ["pro_yearly"],
"window": { "last_days": 30 }
}
]
}
]
}
}'{
"segment": {
"id": "gk3x",
"name": "iOS pro buyers, 30 days",
"definition_hash": "f7e6d5c4…",
"size": null,
"…": "…"
}
}Archive a segment
/api /v1 /sdk /server /segments /{segment_id}Archives the segment. It is not deleted: it stops being evaluated, drops out of the list and cannot be targeted. Restore it with Update a segment and archived: false.
PROJECT-KEYstringRequiredYour project key.
ENVIRONMENTstringRequiredproduction or test.
segment_idstringRequiredThe segment's id.
Returns 200 with a message.
Errors
curl -X DELETE "https://sdk.sqd.link/api/v1/sdk/server/segments/{segment_id}" \
-H "PROJECT-KEY: $GROVS_PROJECT_KEY" \
-H "ENVIRONMENT: production"{
"message": "Segment archived"
}Count a segment
/api /v1 /sdk /server /segments /{segment_id} /countReturns the exact number of people and devices in a saved segment. The first count after a change can take a few seconds. The result is reused for a few minutes, so repeat calls are fast.
Server counts run in their own pool, apart from the dashboard's.
PROJECT-KEYstringRequiredYour project key.
ENVIRONMENTstringRequiredproduction or test.
segment_idstringRequiredAn active segment's id.
Returns 200 with persons, devices, incomplete and result_id, the ID of the computed result.
Errors
curl -X POST "https://sdk.sqd.link/api/v1/sdk/server/segments/{segment_id}/count" \
-H "PROJECT-KEY: $GROVS_PROJECT_KEY" \
-H "ENVIRONMENT: production"{
"persons": 4821,
"devices": 5310,
"incomplete": false,
"result_id": "3f9a1c2e…"
}{
"error": "Too many segment queries are running; retry shortly.",
"error_code": "segment_busy"
}Replace the identifier list
/api /v1 /sdk /server /segments /{segment_id} /identifier_listStores a list of your user IDs on the segment, replacing any earlier list. Match it with an identifier condition and op: "in_list" or "not_in_list". Use it when your server knows who belongs, such as members of a loyalty tier.
Identifiers are stored exactly as sent and compared to the user ID your app sets through the SDK. A failed upload keeps the previous list.
PROJECT-KEYstringRequiredYour project key.
ENVIRONMENTstringRequiredproduction or test.
segment_idstringRequiredAn active segment's id.
identifiersstring[]Required1 to 200,000 strings of 1 to 256 bytes. Duplicates count once.
Returns 200 with the updated segment and count, the number of distinct identifiers stored.
Errors
curl -X POST "https://sdk.sqd.link/api/v1/sdk/server/segments/{segment_id}/identifier_list" \
-H "PROJECT-KEY: $GROVS_PROJECT_KEY" \
-H "ENVIRONMENT: production" \
-H "Content-Type: application/json" \
-d '{
"identifiers": ["member-4471", "member-9021", "member-4471"]
}'{
"segment": {
"id": "gk3x",
"has_identifier_list": true,
"identifier_list": { "count": 2, "updated_at": "2026-10-22T09:14:03.120Z" },
"…": "…"
},
"count": 2
}{
"error": "the list needs between 1 and 200000 identifiers"
}