Segments
Contact segments — reusable audience definitions built from conditions (tags, channel, status, custom fields, activity) or a static list of members. Used when composing broadcasts and as automation triggers. Audience size can be previewed without saving a segment via /segments/estimate.
Condition types
Supported condition types: tag, channel, status, date, field, activity, custom; conditions are combined with group_logic (and or or).
Pagination and search
Listing (GET /segments) supports pagination (page, perPage — default 50) and search (search).
Static segments: member identifier
In a static segment (type: "static"), each member (members[]) is identified by identifier — a phone number. Since these are usually pasted from spreadsheets and CRM exports, the server (since 2026-09-09, on POST /segments, POST|PATCH /segments/{segment}, and POST /segments/estimate) normalizes the value before validation: it strips whitespace, parentheses, dashes and surrounding quotes, drops an international 00 prefix, and maps the Kazakhstani/Russian 11-digit form with a leading 8 (8XXXXXXXXXX) to +7XXXXXXXXXX. After normalization the value must be a phone number shaped +<digits> (7–15 digits, no leading zero) — otherwise the request is rejected with 422 and an error on members.N.identifier: Each member identifier must be a phone number in international format (7–15 digits). Duplicates that coincide after normalization collapse into a single member. The response returns members[].identifier already normalized.
Endpoints
| Method | Path | Summary |
|---|---|---|
| GET | /v1/segmentsList segments (paginated, searchable) | List segments (paginated, searchable) |
| POST | /v1/segmentsCreate a segment | Create a segment |
| PATCH | /v1/segments/{segment}Update a segment | Update a segment |
| POST | /v1/segments/{segment}Update a segment (POST alias of PATCH for clients without PATCH) | Update a segment (POST alias of PATCH for clients without PATCH) |
| DELETE | /v1/segments/{segment}Delete a segment | Delete a segment |
| POST | /v1/segments/estimateEstimate audience size from conditions (without saving) | Estimate audience size from conditions (without saving) |
Examples
Create a dynamic segment
Request
curl -X POST https://api.aisar.app/v1/segments \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "New leads",
"description": "Contacts with recent inbound activity",
"conditions": [
{ "type": "tag", "operator": "has_any", "value": [1, 2], "group": 0 },
{ "type": "channel", "operator": "in", "value": [7], "group": 0 }
],
"group_logic": "and"
}'Response
{
"data": {
"id": "45",
"name": "New leads",
"slug": "new-leads",
"type": "dynamic",
"description": "Contacts with recent inbound activity",
"conditions": [
{ "group": 0, "type": "tag", "operator": "has_any", "value": [1, 2], "field_name": null },
{ "group": 0, "type": "channel", "operator": "in", "value": [7], "field_name": null }
],
"conditions_summary": "Tag in (Lead, Hot) AND channel is WhatsApp",
"estimated_count": 120,
"contacts_count": null,
"members": null,
"created_at": "2026-03-15T10:00:00.000000Z",
"updated_at": "2026-03-15T10:00:00.000000Z"
}
}Estimate audience without saving
Request
curl -X POST https://api.aisar.app/v1/segments/estimate \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"conditions": [
{ "type": "tag", "operator": "has_any", "value": [1, 2], "group": 0 }
]
}'Response
{
"data": {
"estimated_count": 120
}
}Update a segment
Request
curl -X PATCH https://api.aisar.app/v1/segments/46 \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Hot leads",
"description": "High-intent contacts from priority channels",
"conditions": [
{ "type": "tag", "operator": "has_any", "value": [2], "group": 0 },
{ "type": "status", "operator": "is", "value": "open", "group": 0 }
],
"group_logic": "and"
}'Response
{
"data": {
"id": "46",
"name": "Hot leads",
"slug": "hot-leads",
"type": "dynamic",
"description": "High-intent contacts from priority channels",
"conditions": [
{ "group": 0, "type": "tag", "operator": "has_any", "value": [2], "field_name": null },
{ "group": 0, "type": "status", "operator": "is", "value": "open", "field_name": null }
],
"conditions_summary": "Tag in (Hot) AND status is open",
"estimated_count": 64,
"contacts_count": null,
"members": null,
"created_at": "2026-03-15T10:00:00.000000Z",
"updated_at": "2026-03-16T09:30:00.000000Z"
}
}Static segment from a pasted number list (normalization and dedup)
Request
curl -X POST https://api.aisar.app/v1/segments \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Conference attendees",
"type": "static",
"members": [
{ "identifier": "1 (202) 555-01-87", "display_name": "Aigerim" },
{ "identifier": "\"905336607106\"" },
{ "identifier": "0012025550187" }
]
}'Response
{
"data": {
"id": "52",
"name": "Conference attendees",
"slug": "conference-attendees",
"type": "static",
"description": null,
"conditions": [],
"conditions_summary": null,
"estimated_count": null,
"contacts_count": 2,
"members": [
{ "identifier": "+12025550187", "display_name": "Aigerim" },
{ "identifier": "+905336607106", "display_name": null }
],
"created_at": "2026-09-09T10:00:00.000000Z",
"updated_at": "2026-09-09T10:00:00.000000Z"
}
}Error: identifier is not a phone number
Request
curl -X POST https://api.aisar.app/v1/segments \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Broken import",
"type": "static",
"members": [
{ "identifier": "email:client@example.com" }
]
}'Response
{
"message": "The members.0.identifier field format is invalid.",
"errors": {
"members.0.identifier": [
"Each member identifier must be a phone number in international format (7\u201315 digits)."
]
}
}