Create segment
If you have questions regarding this API, please visit our API FAQ page.
Creating a segment
Make a POST request to https://webapi.inboxroad.com/api/v2/segments/ with a
valid X-API-Key.
curl -X POST 'https://webapi.inboxroad.com/api/v2/segments/' \ -H 'X-API-Key: <your_token>' \ -H 'Content-Type: application/json' \ -d '{ "name": "Active Gmail Subscribers", "color": "#7cb7de", "contact_list_ids": ["0fd3d5b4-1c0a-4e91-8a4f-0f17dc6dc5ab"], "rules_json": { "any": [ { "all": [ { "kind": "field", "field": "status", "operator": "equals", "value": "subscribed" }, { "kind": "activity", "metric": "open", "operator": "count_gte", "value": 1, "days_window": { "mode": "last", "days": 30 } } ] } ] } }'Request fields
| Field name | Required | Description |
|---|---|---|
| name | Yes | Name of the segment. |
| color | Yes | Hex color from the allowed palette. |
| contact_list_ids | Yes | Contact list ids (UUIDs) the segment draws from. At least one is required; an empty list is rejected with 400. |
| rules_json | Yes | The segment definition. See Segment rules below. |
| description | No | Optional description. |
Segment rules
rules_json is a nested boolean expression:
{ "any": [ { "all": [ <condition>, ... ] }, ... ] }anyis a list of rule groups combined with OR.- Each group’s
allis a list of conditions combined with AND.
Each condition is an object with a kind discriminator. The available kinds:
field — match a contact field
{ "kind": "field", "field": "<column_name>", "operator": "<op>", "value": <value> }field is a contact column on one of the selected lists — see the
sorted_fields array in Get contact list. A field’s label is
accepted as well as its column_name; it is normalised to the snake-cased
column name.
Which operators you may use depends on that column’s data_type:
data_type | Allowed operators |
|---|---|
text, character, email, pattern, choice | equals, not_equals, contains, not_contains, starts_with, in, not_in, is_null, is_not_null |
integer, float | equals, gt, gte, lt, lte, is_null, is_not_null |
date, datetime | equals, gt, gte, lt, lte, is_null, is_not_null |
boolean | equals, not_equals, is_null, is_not_null |
multichoice | equals, not_equals, has_any, has_all, has_none, is_null, is_not_null |
Note that not_equals is not available on numeric or date columns, and the
list operators has_any / has_all / has_none apply only to multichoice.
value is required for every operator except is_null and is_not_null, which
take none. in, not_in, has_any, has_all and has_none take a
non-empty list. The value must be castable to the column’s data_type — a
string where an integer column is expected fails the build.
activity — open / click activity
{ "kind": "activity", "metric": "open", "operator": "count_gte", "value": 1, "days_window": { "mode": "last", "days": 30 }, "include_campaign_ids": [], "exclude_campaign_ids": [] }metric:openorclick.operator:ever,never,count_gte,count_lte,count_eq.valueis required (and ≥ 0) for thecount_*operators and must be omitted forever/never.days_window(optional):{ "mode": "last" | "more_than", "days": <int > 0> }.include_campaign_ids/exclude_campaign_ids(optional): cannot be used together.
membership — membership in other lists
{ "kind": "membership", "operator": "in", "list_ids": ["<uuid>", ...] }operator: in or not_in. list_ids requires at least one UUID.
deliverability — bounce / complaint / delivery activity
{ "kind": "deliverability", "metric": "bounce", "operator": "count_gte", "value": 1, "days_window": { "mode": "last", "days": 90 } }metric:bounce,complaint,delivered,unsubscribe.operator:ever,count_gte,count_lte,count_eq.valueis required forcount_*and omitted forever.
isp — recipient ISP
{ "kind": "isp", "operator": "in", "values": [1, 2] }operator: in or not_in. values is a list of ISP alias ids.
When rules are checked
Only the shape of rules_json is validated while the request is being
handled: the kind discriminator, the operator and metric enums, and the
value rules on activity and deliverability conditions. Those failures come
back as 422.
Field conditions are not checked against the lists’ field schema at that point. The segment is stored and built asynchronously, so a mistake there surfaces only afterwards:
| Mistake | What happens |
|---|---|
field names a column that none of the selected lists has | That condition matches nothing. The build still succeeds and the segment reaches DONE, but smaller — often empty. |
The operator is not allowed for the column’s data_type | The build fails and the segment ends in status FAILED. No further error detail is exposed through the API. |
Response
The build starts immediately, so the returned segment begins in status
PENDING and transitions to DONE once total_count is known. The response
shape matches Get segment.
{ "id": "92a6ef72-c74e-4e37-bd84-9e8fbb83fef4", "name": "Active Gmail Subscribers", "color": "#7cb7de", "description": null, "rules_json": { "any": [ { "all": [ /* ... */ ] } ] }, "contact_list_ids": ["0fd3d5b4-1c0a-4e91-8a4f-0f17dc6dc5ab"], "status": "PENDING", "total_count": null, "created_at": "2026-05-21T11:30:00Z", "updated_at": "2026-05-21T11:30:00Z", "display_fields": []}Possible response codes
| Status code | Description |
|---|---|
| 200 | Segment created successfully (build started). |
| 400 | One of contact_list_ids does not exist, contact_list_ids is empty, or the color is not in the palette. |
| 401 | Unauthorized. |
| 422 | Body failed validation — missing required field, or malformed rules_json (e.g. a condition with an unknown kind). |
| 429 | Rate limit exceeded. See Rate limiting. |