Create a dynamic Segment

Search Documentation

Search across all developer documentation

segments

Create a dynamic Segment

POST /v1/segments
Auth required api.segments.manage

Creates a managed Segment definition and evaluates its predicate before returning, so the 201 carries the number of contacts it matches: member_count with evaluation: "complete", or a null count with evaluation: "queued" when the evaluation exceeded its budget and a background reconcile took over. A null count is never a zero — zero means the predicate matched nobody.

key is optional and defaults to a slug of the name; it is the stable org-unique handle every other call addresses the Segment by, and it is immutable afterwards. A key already in use returns 409 conflict.

A predicate that does not compile is still saved, with status: "invalid" and the reason — work in progress is not thrown away — but a predicate that names something the org does not have returns 422 validation_failed positioned at the fault, with the org's real attribute names in candidates. Lint first with POST /v1/segments/validate and size it with POST /v1/segments/preview.

Saving a Segment mails nobody: a broadcast or a workflow is what sends.

Request body

Content type: application/json

name string optional
key string optional

Optional on create — the org-unique slug (lowercase letters, digits, hyphen, underscore; starts with a letter; up to 63 chars). Defaults to a slug of the name. Ignored on edit.

description string optional
source string optional

The SendQL predicate whose live truth value defines membership. Lint it with POST /v1/segments/validate and size it with POST /v1/segments/preview first.

expected_content_hash string optional

Edit only. The content_hash the caller last read. When present, an edit whose stored hash has moved on is refused with 409 conflict carrying the current hash. Omit for no concurrency check.

Responses

Errors follow the RFC 7807 problem format — see the error reference.

201 The created Segment, with its evaluated member count application/json
id string<uuid> required
name string required
key string required

Org-unique slug, stable across renames.

description string required
source string required

The SendQL predicate that defines membership.

profile_version integer required

SendQL profile version the source was compiled under.

eval_class string enum required

How membership is reconciled: incremental (re-evaluated on an attribute change), sweep (periodic full re-evaluation, for time-relative or event predicates), or both.

One of: incremental, sweep, both

status string enum required

invalid means the predicate no longer compiles (e.g. a referenced attribute was deleted); fix the predicate with PUT /v1/segments/{id} to re-activate. archived is a retired segment — deactivated but preserved.

One of: active, paused, invalid, archived

member_count integer<int64> | null required

Cached count of current members from the last reconcile, and null when the segment has never been evaluated. Null is not zero: zero means the predicate matched nobody, null means nothing has asked yet. A newly created segment is null only until its first evaluation completes — see evaluation.

evaluation string enum optional

Present only on a write response. complete means the save evaluated the membership before returning and member_count is that answer; queued means the evaluation exceeded its budget or failed, a background reconcile was enqueued, and member_count is null until it finishes. Absent on reads.

One of: complete, queued

eval_warning string optional

A standing "evaluation disrupted" warning, present when an attribute the predicate references was mutated disruptively (renamed or retyped via the management API). The segment keeps evaluating best-effort; the warning clears when the predicate is re-saved. Absent when the segment is healthy.

eval_warning_at string<date-time> optional

Time the standing eval_warning was raised; absent when none.

last_evaluated_at string<date-time> optional

Time of the last reconcile; absent until the first evaluation.

content_hash string optional

The optimistic-concurrency token over the segment's author-editable definition. Send it back as expected_content_hash on PUT /v1/segments/{id} and the edit is refused (409) rather than clobbering a concurrent one. Absent on a row that predates the column, until its next managed write recomputes it.

warnings array<string> optional

Non-blocking findings from the SendQL analyzer for the definition just saved — present only on a write response. A segment with warnings is saved, not rejected.

requires array<object> optional

Everything this definition still depends on, with each dependency's state. Present on the write responses and on the detail read (the polling surface); absent on the collection read. An empty array means nothing is outstanding — see V1Requirement.

Each entry in requires:

kind string enum required

The namespace key is looked up in. Branch on this; never parse detail.

One of: template, segment, list, topic, identity, channel, attribute, activity_property, asset

key string required

The identifier as the definition names it — a template name, a segment id or key, a from-address. Empty for a requirement about the ABSENCE of a reference: a send with no topic at all names no topic.

status string enum required

ok — resolves and is usable now. missing — nothing in this organization answers to that key. Correct the reference, or create the thing. not_ready — it exists, in a state that cannot be used yet. Usually a wait, and retrying the identical request is the move. Treating this as missing sends you hunting for a typo that is not there.

One of: ok, missing, not_ready

detail string required

The state, in the words that say which state — deploy_state=pending, member_count=null (evaluation queued). For display and logs; do not parse it.

fix string required

The call that clears this requirement, as an HTTP route where there is one and as a plain instruction where there is not (a template deploy is waited for, not called). Empty on an ok entry.

created_at string<date-time> required
updated_at string<date-time> required
401 Missing, malformed, or unknown API key application/problem+json
403 Key lacks the required scope or plan limit violated application/problem+json
409 The mutation is rejected by a state rule rather than a bad request. The code is conflict. application/problem+json
422 A query parameter, path value or body field failed validation. The body is a validation_failed Problem. When the refusal is about a reference — a segment key, template slug, topic or attribute name the organization does not have — it additionally carries validation_code, field, line/column, missing, candidates and next_step, so a client can correct the call without a second round of guessing. See ValidationProblem. application/problem+json
429 Per-org rate limit exceeded application/problem+json
500 Unexpected server-side failure. The code is internal_error. The request_id field can be quoted to SendOps support to investigate. application/problem+json