UC-023 — Advanced Contact Segmentation
| Field | Value |
|---|---|
| ID | UC-023 |
| Goal | Segment contacts with advanced filters to create targeted lists |
| Channel | All |
| Complexity | ⭐⭐⭐ Advanced |
| Estimated time | 30 minutes |
| APIs involved | GET /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
- Standard filters:
search(name),gender,isValid,communicationSupported,isTest,phoneNumber,email,lastContactType,lastCampaignType,listIdsandnotListIdscan be filtered directly as query parameters. - Custom fields:
customField1,customField2andcustomField3, likecityandtags, are returned with every contact but are not query parameters: select on them client-side, or let a smart list match them through thefiltersofPOST /contacts/list(e.g.{"field": "customField1", "operand": "equals", "value": "Lombardia"}), evaluated on every send. - Pagination: Use
page(starting at 0) andlimitto paginate large result sets; the response carriestotalCountandtotalPages. The maximum forlimitis 1000. - Sorting: Use
sortBy=field&sortOrder=asc|descto sort results (by default byfullName, ascending). - 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.
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
| Step | Action | Result |
|---|---|---|
| 1 | GET /contacts?isValid=true | Reachable contacts, Lombardy ones selected on customField1 |
| 2 | POST /contacts/list | New segmented list created |
| 3 | POST /contacts/list/contacts | VIP 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
- UC-007 — Manage Contacts and Lists: Import contacts from CSV and VCard
- UC-006 — Bulk SMS Campaign: Use the segmented list in an SMS campaign
- UC-022 — Bulk WhatsApp Campaign: Send to the VIP list via WhatsApp
- UC-028 — Compliance Opt-out GDPR: Manage opt-out and GDPR compliance
References
- API Reference — Contacts: Full contact endpoint documentation
- Contacts and Lists Guide: Best practices for contact management
- Authentication Guide: Details on API Key and Basic Auth