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}, DELETE /contacts/{id}, POST /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 contacts applying region filters.
curl -X GET "https://lora-api.agiletelecom.com/api/partner-gateway/v1/contacts?region=Lombardia&limit=50&offset=0" \
-H "X-Api-Key: YOUR_API_KEY"
Response — Filtered contacts
{
"contacts": [
{
"id": "cnt-001",
"firstName": "Marco",
"lastName": "Rossi",
"phoneNumber": "+393471234567",
"email": "marco.rossi@email.it",
"region": "Lombardia",
"customFields": {
"lastPurchaseDate": "2026-03-15",
"totalSpent": 1250.00,
"preferredChannel": "WHATSAPP"
}
},
{
"id": "cnt-002",
"firstName": "Laura",
"lastName": "Bianchi",
"phoneNumber": "+393489876543",
"email": "laura.bianchi@email.it",
"region": "Lombardia",
"customFields": {
"lastPurchaseDate": "2026-01-10",
"totalSpent": 6800.00,
"preferredChannel": "SMS"
}
}
],
"total": 4350,
"limit": 50,
"offset": 0
}
Behind the scenes — Available filters and query logic
- Standard filters:
region,city,firstName,lastName,email,phoneNumbercan be filtered directly as query parameters. - Custom fields: Fields in
customFieldscan be filtered using the syntaxcustomFields.fieldname=value. - Pagination: Use
limitandoffsetto paginate large result sets. The maximum forlimitis 100. - Sorting: Use
sort=field&order=asc|descto sort results (e.g.,sort=customFields.totalSpent&order=desc). - 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://lora-api.agiletelecom.com/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": "list-vip-lombardia-001",
"name": "VIP Lombardia - Spesa > 5000 EUR",
"description": "Clienti lombardi con spesa totale superiore a 5000 EUR",
"contactCount": 0,
"createdAt": "2026-04-09T11:00:00+02:00"
}
Step 3 — Add contacts to the segmented list
Add the filtered contacts to the new list using their IDs.
curl -X POST https://lora-api.agiletelecom.com/api/partner-gateway/v1/contacts/list/contacts \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"listId": "list-vip-lombardia-001",
"contactIds": ["cnt-002", "cnt-015", "cnt-089", "cnt-142", "cnt-278"]
}'
Response — Contacts added
{
"listId": "list-vip-lombardia-001",
"addedContacts": 5,
"duplicateContacts": 0,
"invalidContacts": 0,
"totalContactsInList": 5
}
:::tip 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
| Step | Action | Result |
|---|---|---|
| 1 | GET /contacts?region=Lombardia | Filtered list of Lombardy contacts |
| 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 VIP Lombardy contacts (with pagination)
CONTACTS=$(curl -s -X GET \
"https://lora-api.agiletelecom.com/api/partner-gateway/v1/contacts?region=Lombardia&limit=100&offset=0" \
-H "X-Api-Key: YOUR_API_KEY")
# 2. Filter client-side for spending > 5000 EUR
VIP_IDS=$(echo "$CONTACTS" | jq -r '[.contacts[] | select(.customFields.totalSpent > 5000) | .id] | join(",")')
echo "VIP IDs: $VIP_IDS"
# 3. Create the segmented list
LIST_ID=$(curl -s -X POST https://lora-api.agiletelecom.com/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
IDS_JSON=$(echo "$CONTACTS" | jq '[.contacts[] | select(.customFields.totalSpent > 5000) | .id]')
curl -s -X POST https://lora-api.agiletelecom.com/api/partner-gateway/v1/contacts/list/contacts \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d "{
\"listId\": \"${LIST_ID}\",
\"contactIds\": ${IDS_JSON}
}" | jq .
Variants
Segmentation by inactivity (re-engagement)
Filter contacts who haven't purchased in over 90 days:
curl -X GET "https://lora-api.agiletelecom.com/api/partner-gateway/v1/contacts?customFields.lastPurchaseDate.before=2026-01-09&limit=100" \
-H "X-Api-Key: YOUR_API_KEY"
Remove a contact from a list
If a contact should no longer belong to a segment:
curl -X DELETE "https://lora-api.agiletelecom.com/api/partner-gateway/v1/contacts/list/contacts?listId=list-vip-lombardia-001&contactId=cnt-278" \
-H "X-Api-Key: YOUR_API_KEY"
Common errors
400 Bad Request — Invalid filter
{
"status": "fail",
"data": {
"filter": "Unknown filter field: invalidField"
}
}
Solution: Verify the filterable field names. For custom fields use the syntax customFields.fieldName.
404 Not Found — Contact not found
{
"status": "fail",
"data": {
"contactId": "Contact not found: cnt-999"
}
}
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
{
"status": "fail",
"data": {
"authentication": "Invalid or missing 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