UC-020 — Import Contacts from VCard
| Field | Value |
|---|---|
| ID | UC-020 |
| Goal | Import contacts from VCard files and verify the import |
| Channel | All |
| Complexity | Intermediate |
| Estimated time | 10 minutes |
| APIs involved | POST /api/partner-gateway/v1/contacts/upload/vcard, GET /api/partner-gateway/v1/contacts/list/{listId}/contacts |
Real-world scenarios
- Migrate from CRM: SalesForce-Pro exports contacts from the old CRM in VCard format and imports them into the Qlara platform to launch SMS campaigns.
- Import from phone: The sales representative exports the company phone's address book to .vcf and uploads it to create a business contact list.
- Sync Outlook: The marketing team periodically syncs Outlook contacts exported in VCard to keep mailing lists up to date.
Import flow
The diagram shows the complete flow: file upload, parsing, saving and verification.
Prerequisites
- Active API Key with contact management permissions
- VCard file (.vcf) in vCard 3.0 or 4.0 format
- Destination list already created (or create a new one with the import)
- Sufficient contact quota (check with UC-016)
Step 1 — Upload the VCard file
Send the .vcf file via multipart form-data specifying the destination list.
curl -X POST https://lora-api.agiletelecom.com/api/partner-gateway/v1/contacts/upload/vcard \
-H "X-Api-Key: YOUR_API_KEY" \
-F "file=@/path/to/contacts-export.vcf" \
-F "listId=list_crm_migration" \
-F "duplicateStrategy=SKIP" \
-F "tags=crm-import,q2-2026"
Response — Import completed
{
"importId": "imp_v1c2a3r4d5",
"listId": "list_crm_migration",
"status": "COMPLETED",
"summary": {
"total": 250,
"imported": 230,
"duplicates": 15,
"errors": 5,
"skipped": 20
},
"errors": [
{
"line": 45,
"name": "Luca Verdi",
"reason": "Invalid phone number format"
},
{
"line": 89,
"name": "Anna Neri",
"reason": "Missing phone number"
}
],
"completedAt": "2026-04-09T11:00:15+02:00"
}
:::tip Duplicate strategy
The duplicateStrategy parameter controls behavior when contacts already exist:
SKIP: Ignore duplicates (default)UPDATE: Update existing contact fieldsDUPLICATE: Create a copy (not recommended) :::
Behind the scenes — VCard file parsing
- Format validation: The parser verifies that the file is a valid VCard (header
BEGIN:VCARD, footerEND:VCARD). - Field extraction: The fields
FN(full name),TEL(phone),EMAILandADR(address) are extracted. TheTELfield is mandatory. - Number normalization: Phone numbers are normalized to E.164 format (e.g.
347 123 4567becomes+393471234567). If the international prefix is missing, the account default is applied. - Deduplication: Contacts are compared by normalized phone number. The chosen strategy (
SKIP,UPDATE) determines the behavior. - Tagging: The specified tags are associated with all imported contacts to facilitate future segmentation.
Step 2 — Verify imported contacts
Retrieve the contact list to verify that the import was successful.
curl -X GET "https://lora-api.agiletelecom.com/api/partner-gateway/v1/contacts/list/list_crm_migration/contacts?limit=10" \
-H "X-Api-Key: YOUR_API_KEY"
Response — Contacts in the list
{
"listId": "list_crm_migration",
"contacts": [
{
"contactId": "cnt_001",
"name": "Marco Rossi",
"phoneNumber": "+393471234567",
"email": "marco.rossi@email.com",
"tags": ["crm-import", "q2-2026"],
"createdAt": "2026-04-09T11:00:10+02:00"
},
{
"contactId": "cnt_002",
"name": "Giulia Bianchi",
"phoneNumber": "+393489876543",
"email": "g.bianchi@company.it",
"tags": ["crm-import", "q2-2026"],
"createdAt": "2026-04-09T11:00:10+02:00"
}
],
"total": 230,
"page": 1,
"totalPages": 23,
"hasMore": true
}
Behind the scenes — Indexing and search
- Indexing: After import, contacts are indexed by name, phone and email to enable fast searches.
- Segmentation: Tags assigned during import allow creating dynamic segments for campaigns.
- Quota: Each imported contact counts toward the subscription quota. Skipped duplicates do not consume additional quota.
Expected result
| Step | Action | Result |
|---|---|---|
| 1 | POST /contacts/upload/vcard | File imported, summary with counts |
| 2 | GET /contacts/list/{listId}/contacts | Contacts visible in the list with tags |
Complete end-to-end example
Scenario SalesForce-Pro: contact migration from the old CRM.
# 1. Check available contact quota
echo "=== Contact Quota ==="
curl -s -X GET https://lora-api.agiletelecom.com/api/v1/partner-gateway/subscription/contacts \
-H "X-Api-Key: YOUR_API_KEY" | jq '{used, total, available: (.total - .used)}'
# 2. Import the VCard file
echo "=== VCard Import ==="
IMPORT_RESULT=$(curl -s -X POST https://lora-api.agiletelecom.com/api/partner-gateway/v1/contacts/upload/vcard \
-H "X-Api-Key: YOUR_API_KEY" \
-F "file=@./crm-export-2026-04.vcf" \
-F "listId=list_crm_migration" \
-F "duplicateStrategy=SKIP" \
-F "tags=crm-import,q2-2026")
echo "$IMPORT_RESULT" | jq '.summary'
# 3. Verify imported contacts
LIST_ID=$(echo "$IMPORT_RESULT" | jq -r '.listId')
echo "=== First 5 imported contacts ==="
curl -s -X GET "https://lora-api.agiletelecom.com/api/partner-gateway/v1/contacts/list/${LIST_ID}/contacts?limit=5" \
-H "X-Api-Key: YOUR_API_KEY" | jq '.contacts[] | {name, phoneNumber, tags}'
Variants
Import with existing contact update
If you want to update the data of already existing contacts (e.g. new email address):
curl -X POST https://lora-api.agiletelecom.com/api/partner-gateway/v1/contacts/upload/vcard \
-H "X-Api-Key: YOUR_API_KEY" \
-F "file=@./contacts-updated.vcf" \
-F "listId=list_crm_migration" \
-F "duplicateStrategy=UPDATE"
Import into a new list
To automatically create a new list during import:
curl -X POST https://lora-api.agiletelecom.com/api/partner-gateway/v1/contacts/upload/vcard \
-H "X-Api-Key: YOUR_API_KEY" \
-F "file=@./outlook-contacts.vcf" \
-F "listName=Outlook Sync Aprile 2026" \
-F "duplicateStrategy=SKIP"
Common errors
400 Bad Request — Invalid VCard file
{
"status": "fail",
"data": {
"file": "Invalid VCard format. Expected BEGIN:VCARD header."
}
}
Solution: Verify that the file is a valid VCard (v3.0 or v4.0). Open the file with a text editor and check that it starts with BEGIN:VCARD.
413 Payload Too Large — File too large
{
"status": "fail",
"data": {
"file": "File size exceeds maximum allowed (10 MB)"
}
}
Solution: Split the VCard file into smaller files (max 10 MB each) and import them separately.
409 Conflict — Contact quota exhausted
{
"status": "fail",
"data": {
"contacts": "Contact quota exceeded. Current: 50000/50000. Upgrade your plan to import more contacts."
}
}
Solution: You have reached your plan's contact limit. Delete unnecessary contacts or upgrade your plan.
Next steps
- UC-007 — Manage Contacts and Lists: Manage and segment imported contacts
- UC-006 — Bulk SMS Campaign: Send a campaign to the newly imported list
- UC-016 — Monitor Credit and Subscription: Check quota and credit before sending