Skip to main content

UC-023 — Advanced Contact Segmentation

FieldValue
IDUC-023
GoalSegment contacts with advanced filters to create targeted lists
ChannelAll
Complexity⭐⭐⭐ Advanced
Estimated time30 minutes
APIs involvedGET /api/partner-gateway/v1/contacts, POST /contacts, PUT /contacts/{id}, POST /contacts/list, POST /contacts/list/contacts, DELETE /contacts/list/contacts

Real-world scenarios​

  • TurismoVeneto — Segment by region: Filter 20,000 contacts by region of residence and create separate lists for Lombardy, Veneto and Emilia-Romagna for geo-targeted promotions.
  • LuxuryStore — VIP list: Identify customers with total spending above 5,000 EUR and create a VIP list for exclusive previews and private event invitations.
  • FreshMarket — Filter by last purchase: Select customers who haven't purchased in over 90 days for a re-engagement campaign with discount coupons.

Segmentation flow​

The diagram shows the flow: from the full list, multiple filters (region, attributes, date) are applied to create segmented lists ready for campaigns.

Prerequisites​

  • Active API Key with contact management permissions
  • Contacts imported into the platform (see UC-007)
  • At least one existing contact list with populated custom fields

Step 1 — Retrieve contacts with filters​

Query the contacts with the filters supported by GET /contacts, here only the reachable ones (isValid=true). The region is not a query parameter: in this example it is stored in customField1, with the total spent in customField2 and the last purchase date in customField3 (set at import or with PUT /contacts/{id}), and you select on these fields in your code.

curl -X GET "https://api.qlara.ai/api/partner-gateway/v1/contacts?isValid=true&page=0&limit=50" \
-H "X-Api-Key: YOUR_API_KEY"

Response — Filtered contacts​

{
"data": [
{
"id": 30112,
"fullName": "Marco Rossi",
"firstName": "Marco",
"lastName": "Rossi",
"phoneNumbers": ["+393471234567"],
"emailAddresses": ["marco.rossi@email.it"],
"mobilePhoneNumber": "+393471234567",
"isValidMobilePhoneNumber": true,
"city": "Milano",
"customField1": "Lombardia",
"customField2": "1250.00",
"customField3": "2026-03-15"
},
{
"id": 30113,
"fullName": "Laura Bianchi",
"firstName": "Laura",
"lastName": "Bianchi",
"phoneNumbers": ["+393489876543"],
"emailAddresses": ["laura.bianchi@email.it"],
"mobilePhoneNumber": "+393489876543",
"isValidMobilePhoneNumber": true,
"city": "Bergamo",
"customField1": "Lombardia",
"customField2": "6800.00",
"customField3": "2026-01-10"
}
],
"page": 0,
"limit": 50,
"totalCount": 18640,
"totalPages": 373
}
Behind the scenes — Available filters and query logic
  1. Standard filters: search (name), gender, isValid, communicationSupported, isTest, phoneNumber, email, lastContactType, lastCampaignType, listIds and notListIds can be filtered directly as query parameters.
  2. Custom fields: customField1, customField2 and customField3, like city and tags, are returned with every contact but are not query parameters: select on them client-side, or let a smart list match them through the filters of POST /contacts/list (e.g. {"field": "customField1", "operand": "equals", "value": "Lombardia"}), evaluated on every send.
  3. Pagination: Use page (starting at 0) and limit to paginate large result sets; the response carries totalCount and totalPages. The maximum for limit is 1000.
  4. Sorting: Use sortBy=field&sortOrder=asc|desc to sort results (by default by fullName, ascending).
  5. Combining filters: All filters use logical AND. For complex OR logic, execute multiple queries and combine results client-side.

Step 2 — Create a segmented list​

Create a new list for the identified segment.

curl -X POST https://api.qlara.ai/api/partner-gateway/v1/contacts/list \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"name": "VIP Lombardia - Spesa > 5000 EUR",
"description": "Clienti lombardi con spesa totale superiore a 5000 EUR"
}'

Response — List created​

{
"id": 912,
"name": "VIP Lombardia - Spesa > 5000 EUR",
"description": "Clienti lombardi con spesa totale superiore a 5000 EUR",
"filters": null,
"companyId": 4618,
"numContact": 0,
"isTest": false,
"isDeleted": false,
"createdAt": "2026-04-09 09:00:00.418+0000",
"updatedAt": "2026-04-09 09:00:00.418+0000"
}

Step 3 — Add contacts to the segmented list​

Add the filtered contacts to the new list using their IDs.

curl -X POST https://api.qlara.ai/api/partner-gateway/v1/contacts/list/contacts \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"listIds": [912],
"contactIds": [30113, 30127, 30188, 30241, 30302]
}'

Response — Contacts added​

[88101, 88102, 88103, 88104, 88105]

The response lists the IDs of the associations created.

Automating segmentation

For large lists, automate the process server-side: retrieve all filtered contacts with pagination, collect the IDs and send them in batches to the list. The batch limit is 1,000 contacts.

Expected result​

StepActionResult
1GET /contacts?isValid=trueReachable contacts, Lombardy ones selected on customField1
2POST /contacts/listNew segmented list created
3POST /contacts/list/contactsVIP contacts added to the list

Complete end-to-end example​

# 1. Retrieve the reachable contacts (with pagination)
CONTACTS=$(curl -s -X GET \
"https://api.qlara.ai/api/partner-gateway/v1/contacts?isValid=true&page=0&limit=1000" \
-H "X-Api-Key: YOUR_API_KEY")

# 2. Filter client-side: Lombardy (customField1) with spending > 5000 EUR (customField2)
VIP_IDS=$(echo "$CONTACTS" | jq -c '[.data[] | select(.customField1 == "Lombardia" and ((.customField2 | tonumber?) // 0) > 5000) | .id]')
echo "VIP IDs: $VIP_IDS"

# 3. Create the segmented list
LIST_ID=$(curl -s -X POST https://api.qlara.ai/api/partner-gateway/v1/contacts/list \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"name": "VIP Lombardia - Spesa > 5000 EUR",
"description": "Segmento VIP per campagna esclusiva"
}' | jq -r '.id')

echo "List ID: $LIST_ID"

# 4. Add contacts to the list
curl -s -X POST https://api.qlara.ai/api/partner-gateway/v1/contacts/list/contacts \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d "{
\"listIds\": [${LIST_ID}],
\"contactIds\": ${VIP_IDS}
}" | jq .

Variants​

Segmentation by inactivity (re-engagement)​

Filter contacts who haven't purchased in over 90 days, comparing client-side the last purchase date stored in customField3 (format yyyy-MM-dd):

curl -s -X GET "https://api.qlara.ai/api/partner-gateway/v1/contacts?isValid=true&page=0&limit=1000" \
-H "X-Api-Key: YOUR_API_KEY" | jq -c '[.data[] | select((.customField3 // "") != "" and .customField3 < "2026-01-09") | .id]'

Remove a contact from a list​

If a contact should no longer belong to a segment:

curl -X DELETE https://api.qlara.ai/api/partner-gateway/v1/contacts/list/contacts \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"listIds": [912],
"contactIds": [30302]
}'

Common errors​

Unfiltered results — Unknown filter​

GET /contacts does not reject query parameters it does not recognize: a filter such as region=Lombardia or customField1=Lombardia is ignored, and the response contains every contact the other filters match.

Solution: Use only the standard filters listed under Step 1. For city, tags and the custom fields, select client-side or use a smart list.

404 Not Found — Contact not found​

{
"status": "fail",
"data": {
"contactId": "Contact not found: 999999"
}
}

Solution: The contact ID may have been deleted or may not exist. Verify the ID with a GET before adding to the list.

401 Unauthorized — Missing or invalid API Key​

{
"error": "Invalid API Key"
}

Solution: Verify that the X-Api-Key header is present and that the key is active in the platform dashboard.

Next steps​

References​