Kloyst Contact Upload Feature – Frontend Integration & UX Specification
Overview
This document explains the complete Contact Upload feature for Kloyst from a frontend integration and UX perspective.
The purpose of this document is to help frontend developers clearly understand:
- how the upload flow works
- what validations exist
- how conflict handling works
- how preview and confirmation flows behave
- what APIs/states/errors to expect
- how enterprise-grade ingestion behavior is designed
The backend architecture is already designed to support:
- CSV/XLSX uploads
- asynchronous processing
- chunk-based validation
- intelligent phone parsing
- duplicate detection
- conflict resolution
- contact merging
- import cancellation
- malware scanning
- scalable processing
1. Supported Upload Types
Allowed File Types
Primary
.csv
Secondary
.xlsx
Important Notes
- CSV is the preferred upload format.
- XLSX support exists for business convenience.
- Backend converts all uploads into normalized internal structures.
- Large files are processed asynchronously.
2. Upload Flow (High Level)
User Uploads File
→ Upload Accepted
→ File Queued
→ Malware Scan
→ Parsing
→ Validation
→ Normalization
→ Duplicate Detection
→ Conflict Preview
→ User Confirmation
→ Persistence
→ Import Completed
3. Upload Lifecycle States
Frontend must support the following states.
Upload Job States
| State | Meaning |
|---|---|
| UPLOADED | File uploaded successfully |
| SCANNING | Malware scan in progress |
| QUARANTINED | Suspicious file detected |
| QUEUED | Waiting for workers |
| PROCESSING | Parsing/validation ongoing |
| PENDING_REVIEW | Waiting for user confirmation |
| PARTIAL_SUCCESS | Some contacts failed validation |
| COMPLETED | Import completed successfully |
| FAILED | Import failed |
| CANCELLED | User cancelled import |
4. Upload UX Requirements
Frontend Must Support
- drag & drop upload
- file picker upload
- upload progress indicator
- import status polling
- cancellation button
- preview before final persistence
- downloadable error reports
- downloadable warning reports
5. Contact Parsing Logic
Important Design Rule
One Row != One Contact
A single row may generate multiple contacts.
Example:
Rajiv & Suhail | 9962665705 | 7358559280
Results in:
2 contact records
Frontend preview must display expanded normalized contacts.
6. Phone Number Normalization
All phone numbers are normalized into:
E.164 format
Example:
9840844448
→ +919840844448
Country Detection Strategy
The backend intelligently determines countries using:
- explicit +country code
- known dialing prefixes
- upload default country
- majority-country heuristic
- ambiguous warning fallback
Example
44 7505620411
→ +447505620411
→ UK
7. Validation Categories
Frontend must distinguish clearly between:
Errors (Blocking for Row)
Examples:
- invalid digit count
- malformed numbers
- impossible numbers
- invalid country code
Behavior:
- contact NOT persisted
- row shown as failed
Warnings (Non-Blocking)
Examples:
- duplicate contacts
- ambiguous country
- suspicious formatting
Behavior:
- user may proceed
- contacts may still persist
8. Important UX Rule
Entire Import Must NEVER Fail
Example:
1000 contacts uploaded
980 valid
15 warnings
5 errors
Frontend must show:
- successful contacts
- warnings
- failed rows
- downloadable reports
9. Import Preview Screen
Before persistence, frontend must show:
| Column | Description |
|---|---|
| Display Name | Parsed contact name |
| Normalized Number | E164 number |
| Country | Detected country |
| Validation Status | Valid/Warning/Error |
| Duplicate Status | Existing/New |
| Merge Action | Merge/Skip/Update |
Preview Summary Example
145 existing contacts detected
20 contacts contain updated names
35 contacts contain new labels
5 invalid contacts excluded
10. Labels / Tags
Contacts support labels.
Examples:
- Bride Side
- Groom Side
- Business Guests
- VIP
- Vendors
Label Rules
- labels are optional
- frontend must support label mapping
- frontend must support custom label creation
- soft limit: 10 labels/contact
- duplicate labels are automatically merged
11. Duplicate Handling & Merge Strategies
The backend maintains:
UNIQUE(vendorId, mobile)
Meaning:
- same vendor
- same E164 number = same contact identity
Supported Merge Strategies
| Strategy | Behavior |
|---|---|
| SKIP_DUPLICATES | Ignore incoming duplicate |
| MERGE_LABELS | Merge labels only |
| UPDATE_METADATA | Update names/metadata safely |
| FULL_REPLACE | Aggressive overwrite |
Default Strategy
MERGE_LABELS
Important
FULL_REPLACE is restricted.
Frontend must:
- show warning modal
- require explicit confirmation
- optionally restrict by role
12. Metadata Conflict Rules
Backend applies metadata precedence rules.
Example:
Rajiv Kumar
should NOT be overwritten by:
Rajiv
Current Logic
Priority:
- MANUAL contacts protected
- longer richer names preferred
- non-empty values preferred
Frontend should clearly indicate:
- existing value
- incoming value
- final resolved value
where applicable.
13. Upload Cancellation
Users can cancel imports.
Behavior:
- future chunk processing stops
- queued jobs cleaned up
- already persisted contacts remain
- import marked CANCELLED
Frontend must:
- provide cancel button
- show cancellation state
- disable further actions after cancel
14. Security Requirements
Frontend must support:
- file type restrictions
- upload size restrictions
- upload throttling messaging
- idempotent upload requests
Important
Backend performs:
- malware scanning
- MIME validation
- CSV sanitization
- PII-safe logging
- duplicate prevention
Frontend should NOT assume uploads are immediately trusted.
15. Recommended Frontend Validation
Frontend should perform lightweight fast validation.
Frontend Validation
- allowed file type
- empty file checks
- header validation
- obvious malformed numbers
- duplicate detection inside file
- upload size checks
Backend Validation (Source of Truth)
Backend handles:
- E164 normalization
- country inference
- deduplication
- merge logic
- persistence
- malware scanning
- conflict resolution
Frontend must treat backend responses as authoritative.
16. Import Reports
Frontend must support downloading:
Error Report CSV
Example:
row,error
15,Invalid country code
20,Malformed number
Warning Report CSV
Example:
row,warning
40,Duplicate contact
55,Ambiguous country inferred
17. API Specifications
The following internal APIs drive the entire upload pipeline. Frontend developers must integrate directly with these endpoints.
API Standards
- Authentication: JWT Bearer token required.
- Idempotency: All uploads MUST contain the
Idempotency-Keyheader. - Error Handling: Standard HTTP status codes (400, 404, 500, etc.) apply.
1. Initiate Upload
Endpoint: POST /api/v1/contacts/import
Description: Initiates the upload pipeline, performs file hashing, and queues the job.
Headers:
Idempotency-Key: string (required)
Request (multipart/form-data):
file: CSV or XLSX file (Max 50MB)
Response (201 Created):
{
"jobId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"message": "Upload received and processing started"
}
2. Check Status (Polling)
Endpoint: GET /api/v1/contacts/import/:jobId/status
Description: Returns the real-time progress and row counts.
Response (200 OK):
{
"status": "PROCESSING",
"progress": 45.5,
"stats": {
"totalRows": 15000,
"validRows": 6500,
"invalidRows": 50,
"warningRows": 0
}
}
Note: Polling should stop when status is PENDING_REVIEW, COMPLETED, FAILED, CANCELLED, or QUARANTINED.
3. Fetch Preview
Endpoint: GET /api/v1/contacts/import/:jobId/preview
Description: Fetches the conflict summary and a sample of valid/invalid data for the confirmation screen. Only available during PENDING_REVIEW or PROCESSING.
Response (200 OK):
{
"jobStatus": "PENDING_REVIEW",
"totalValid": 9500,
"totalErrors": 20,
"conflictSummary": {
"totalNewContacts": 9000,
"totalExistingContacts": 500,
"contactsWithUpdatedNames": 250,
"contactsWithNewLabels": 150
},
"validSample": [
{ "name": "Rajiv Kumar", "_normalized": { "e164": "+919840844448", "countryCode": "IN", "nationalNumber": "9840844448" }, "_action": "UPDATE" }
],
"errorSample": [
{ "rowIndex": 15, "rowData": { "Name": "Suhail", "Phone": "123" }, "reason": "No valid phone number found" }
]
}
4. Confirm Import
Endpoint: POST /api/v1/contacts/import/:jobId/confirm
Description: Confirms the preview and initiates the final raw SQL bulk UPSERT. Only allowed when status === 'PENDING_REVIEW'.
Response (201 Created):
{
"status": "PERSISTING",
"jobId": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
}
5. Cancel Import
Endpoint: POST /api/v1/contacts/import/:jobId/cancel
Description: Immediately interrupts active stream parsing and queue workers, halting any future insertions for this job.
Response (201 Created):
{
"status": "CANCELLED",
"message": "Import cancelled successfully"
}
18. Scalability Considerations
The backend is designed for:
- large enterprise uploads
- async processing
- chunked ingestion
- queue-based validation
- partial success workflows
Frontend should:
- avoid assuming synchronous processing
- rely on polling/websocket updates
- support long-running imports gracefully
19. Important Frontend UX Goals
The upload flow should feel:
- safe
- transparent
- informative
- recoverable
- enterprise-grade
Users should ALWAYS understand:
- what failed
- what succeeded
- what got merged
- what got skipped
- what changed
20. Final Notes
The backend architecture already supports:
- enterprise-grade ingestion
- conflict-safe persistence
- duplicate prevention
- smart normalization
- secure uploads
- audit-safe operations
- scalable processing
Frontend implementation should focus heavily on:
- clarity
- preview UX
- progress visibility
- conflict resolution experience
- operational transparency
This is NOT a simple CSV upload flow. It is a production-grade contact ingestion pipeline.