Skip to main content

UC-007 — Manage Contacts and Lists for Campaigns

FieldValue
IDUC-007
GoalImport contacts, create segmented lists, and prepare them for use in campaigns
ChannelAll
ComplexityIntermediate
Estimated time20 minutes
APIs involvedPOST/GET/DELETE /api/partner-gateway/v1/contacts, PUT /contacts/{id}, POST/GET /contacts/list, POST /contacts/list/contacts, POST /contacts/upload, POST /contacts/upload/vcard

Real-world scenarios​

  • ShopItalia — Customer address book import: Import the export from the company CRM (CSV with 5,000 customers) into the platform to prepare the Black Friday campaign.
  • TurismoVeneto — Regional segmentation: Create separate lists for customers in Lombardia, Veneto, and Emilia-Romagna to send geo-targeted promotions on summer stays.
  • Studio Legale Ferrara — Phone address book: Import the corporate address book in VCard format to send institutional communications via SMS.

Prerequisites​

Before you begin, make sure you have:

Test without costs

Add "simulation": true in the request body to validate the flow without actually sending messages and without consuming credit.

Contact management flow​

The diagram shows the three import paths: manual addition, CSV/Excel upload, or VCard import. Uploaded contacts land in the address book and are then added to the list. All paths converge into verification and campaign use.

Step 1 — Create a contact list​

Create an empty list that will serve as a container for the contacts.

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": "Clienti Nord Italia",
"description": "Clienti delle regioni Lombardia, Piemonte, Veneto, Emilia-Romagna"
}'

Response — List created​

{
"id": 87,
"name": "Clienti Nord Italia",
"description": "Clienti delle regioni Lombardia, Piemonte, Veneto, Emilia-Romagna",
"filters": null,
"companyId": 4618,
"numContact": 0,
"isTest": false,
"isDeleted": false,
"createdAt": "2026-04-09 09:00:04.512+0000",
"updatedAt": "2026-04-09 09:00:04.512+0000"
}
Save the list ID

The id field is the identifier you will use to add contacts and associate the list with campaigns.

Step 2a — Add contacts individually​

Create a new contact in the address book and associate it with the list.

curl -X POST https://api.qlara.ai/api/partner-gateway/v1/contacts \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"firstName": "Giulia",
"lastName": "Rossi",
"phoneNumbers": ["+393401234567"],
"emailAddresses": ["giulia.rossi@example.it"],
"gender": "F",
"city": "Milano"
}'

Response — Contact created​

{
"contacts": [
{
"id": 24501,
"fullName": "Giulia Rossi",
"firstName": "Giulia",
"lastName": "Rossi",
"gender": "F",
"phoneNumbers": ["+393401234567"],
"emailAddresses": ["giulia.rossi@example.it"],
"city": "Milano",
"isValidMobilePhoneNumber": true,
"isValidEmail": true,
"mobilePhoneNumber": "+393401234567",
"isTest": false,
"createdAt": "2026-04-09 09:01:12.284+0000"
}
],
"errors": []
}

Associate the contact with the list:

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 '{
"contactIds": [24501],
"listIds": [87]
}'

The response lists the IDs of the associations created:

[90412]
Multiple addition

You can pass multiple contactIds and multiple listIds in a single request to associate N contacts with M lists at once.

Step 2b — Bulk import from CSV​

For mass imports, upload a CSV or Excel file. The process happens in two phases: the upload, which maps the columns and imports the contacts in a single call, then the addition of the imported contacts to the list.

Expected CSV format​

The columns are mapped automatically from the header names, so use the names of the contact fields (such as firstName, lastName, phoneNumber, email):

firstName,lastName,phoneNumber,email
Marco,Bianchi,+393489876543,m.bianchi@example.it
Anna,Verdi,+393331122334,anna.verdi@example.it
Luca,Neri,+393201234567,l.neri@example.it

Phase 1 — Upload and import​

Send the file and its name; removeHead=true keeps the header row from being imported as a contact:

curl -X POST "https://api.qlara.ai/api/partner-gateway/v1/contacts/upload?removeHead=true" \
-H "X-Api-Key: YOUR_API_KEY" \
-F "file=@clienti_nord_italia.csv" \
-F "fileName=clienti_nord_italia.csv"

Response — Import completed​

{
"numContact": 5230,
"addedContact": 5104,
"updatedContact": 98,
"listId": null,
"listName": null,
"numError": 28
}

addedContact counts the new contacts, updatedContact the existing ones (matched by phone number) updated with the file data, and numError the rows that could not be imported. listId and listName are null because the upload has no destination-list parameter: the contacts land in your address book.

Phase 2 — Add the imported contacts to the list​

Find the IDs of the imported contacts with GET /contacts: notListIds=87 returns the contacts that are not in the list yet, up to 1,000 per page. Keep the ones whose phone number is in your file and add them to the list (three IDs shown here):

curl -X GET "https://api.qlara.ai/api/partner-gateway/v1/contacts?notListIds=87&page=0&limit=1000" \
-H "X-Api-Key: YOUR_API_KEY"
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": [87],
"contactIds": [24502, 24503, 24504]
}'

Response — Contacts added to the list​

[90413, 90414, 90415]
Behind the scenes — CSV import process
  1. Upload and parsing: The file is uploaded and parsed, and its columns are mapped to contact fields from their header names. With removeHead=true the header row is not imported as a contact.
  2. Import: In the same call the contacts are saved in the address book (created, or updated as in point 4). They are not added to any list: that is Phase 2.
  3. Number validation: Numbers are validated in international format. Malformed numbers or those without a prefix are discarded.
  4. Deduplication: Contacts whose phone number already exists are updated with the file data instead of being inserted again, and are counted in updatedContact.

Since the mapping is automatic and the import happens in a single call, check the header names and try a small sample file before importing thousands of records.

Step 2c — Import from VCard​

To import contacts from a phone address book in .vcf format:

curl -X POST https://api.qlara.ai/api/partner-gateway/v1/contacts/upload/vcard \
-H "X-Api-Key: YOUR_API_KEY" \
-F "file=@rubrica_aziendale.vcf" \
-F "fileName=rubrica_aziendale.vcf"

Response — VCard imported​

{
"numContact": 342,
"addedContact": 335,
"updatedContact": 4,
"listId": null,
"listName": null,
"numError": 3
}

As with the CSV, the import happens in this single call and the contacts land in the address book: add them to the list as in Phase 2 of Step 2b.

Automatic VCard mapping

Where the CSV relies on its header names, VCard contacts use standard fields (FN, TEL, EMAIL, ADR) that are mapped automatically, with no configuration.

Step 3 — Verify the contacts in the list​

View the contacts present in the list with pagination.

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

Response — Contact listing​

{
"data": [
{
"id": 24501,
"fullName": "Giulia Rossi",
"firstName": "Giulia",
"lastName": "Rossi",
"phoneNumbers": ["+393401234567"],
"emailAddresses": ["giulia.rossi@example.it"],
"mobilePhoneNumber": "+393401234567",
"isValidMobilePhoneNumber": true,
"listIds": [87]
},
{
"id": 24502,
"fullName": "Marco Bianchi",
"firstName": "Marco",
"lastName": "Bianchi",
"phoneNumbers": ["+393489876543"],
"emailAddresses": ["m.bianchi@example.it"],
"mobilePhoneNumber": "+393489876543",
"isValidMobilePhoneNumber": true,
"listIds": [87]
}
],
"page": 0,
"limit": 10,
"totalCount": 5542,
"totalPages": 555
}

Step 4 — Use the list in a campaign​

Pass the list id in the campaign's contactListIds:

curl -X PUT https://api.qlara.ai/api/partner-gateway/v1/campaigns/1542 \
-H "Content-Type: application/json" \
-H "X-Api-Key: YOUR_API_KEY" \
-d '{
"smsSender": "ShopItalia",
"smsBody": "Offerta esclusiva per i clienti del Nord Italia! -30% su tutto con codice NORD30.",
"contactListIds": [87]
}'

See UC-006 — Bulk SMS Campaign for the complete campaign sending flow.

Additional operations​

Remove contacts from a list​

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 '{
"contactIds": [24501],
"listIds": [87]
}'
true

Search contacts by filter​

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

Quick endpoint reference​

ActionMethodEndpoint
List contactsGET/contacts
Create contactPOST/contacts
Update contactPUT/contacts/{id}
Delete contactsDELETE/contacts
List of listsGET/contacts/list
Create listPOST/contacts/list
Add to listPOST/contacts/list/contacts
Remove from listDELETE/contacts/list/contacts
Contacts in listGET/contacts/list/{id}/contacts
Upload CSVPOST/contacts/upload
Upload VCardPOST/contacts/upload/vcard

Common errors​

ProblemProbable causeSolution
HTTP 401Missing or invalid API KeyCheck X-Api-Key header
accepted: falseInsufficient credit or invalid numberCheck credit; verify E.164 format
HTTP 400 — Invalid CSV formatMalformed CSV or missing required columnsVerify the file has a header row and phone numbers in E.164 format
HTTP 409 — Duplicate contactPhone number already exists in the systemUse the existing contact ID or update instead of creating
VCard parse errorUnsupported VCard version or missing TEL fieldEnsure VCard 3.0/4.0 format with valid phone numbers

Expected result​

StepActionResult
1POST /contacts/listList created with id
2aPOST /contacts + POST /contacts/list/contactsContact created and associated with list
2bPOST /contacts/upload + POST /contacts/list/contacts5,202 contacts imported from CSV (5,104 new, 98 updated) and added to the list
2cPOST /contacts/upload/vcard + POST /contacts/list/contacts339 contacts imported from VCard and added to the list
3GET /contacts/list/{id}/contactsPaginated listing of contacts in the list
4PUT /campaigns/{id} with contactListIdsList associated with campaign

Next steps​