Skip to main content

UC-020 — Import Contacts from VCard

FieldValue
IDUC-020
GoalImport contacts from VCard files and verify the import
ChannelAll
ComplexityIntermediate
Estimated time10 minutes
APIs involvedPOST /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 fields
  • DUPLICATE: Create a copy (not recommended) :::
Behind the scenes — VCard file parsing
  1. Format validation: The parser verifies that the file is a valid VCard (header BEGIN:VCARD, footer END:VCARD).
  2. Field extraction: The fields FN (full name), TEL (phone), EMAIL and ADR (address) are extracted. The TEL field is mandatory.
  3. Number normalization: Phone numbers are normalized to E.164 format (e.g. 347 123 4567 becomes +393471234567). If the international prefix is missing, the account default is applied.
  4. Deduplication: Contacts are compared by normalized phone number. The chosen strategy (SKIP, UPDATE) determines the behavior.
  5. 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
  1. Indexing: After import, contacts are indexed by name, phone and email to enable fast searches.
  2. Segmentation: Tags assigned during import allow creating dynamic segments for campaigns.
  3. Quota: Each imported contact counts toward the subscription quota. Skipped duplicates do not consume additional quota.

Expected result

StepActionResult
1POST /contacts/upload/vcardFile imported, summary with counts
2GET /contacts/list/{listId}/contactsContacts 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

References