Lead Import API
Bulk import leads from CSV files with field mapping and deduplication.
POST /leads/import/preview
Upload a CSV file to preview headers and sample rows before importing.
Request
Multipart form data with CSV file.
| Parameter | Type | Required | Description |
|---|---|---|---|
file | file | Yes | CSV file with header row |
Request Example
curl -X POST "https://api.leadvibe.com/leads/import/preview" \
-H "Authorization: Bearer <token>" \
-F "file=@leads.csv"
Response
200 OK
{
"file_id": "preview_abc123",
"file_name": "leads.csv",
"headers": ["Email", "First Name", "Last Name", "Company", "Phone"],
"sample_rows": [
["jane@example.com", "Jane", "Doe", "Example Inc", "+1-555-0100"],
["john@example.com", "John", "Smith", "Acme Corp", "+1-555-0101"]
],
"row_count": 1000,
"auto_detected_identifiers": {
"email_columns": ["Email"],
"phone_columns": ["Phone"]
},
"expires_at": "2025-01-15T11:00:00Z"
}
Response Fields
| Field | Type | Description |
|---|---|---|
file_id | string | Unique identifier for cached file (valid for 1 hour) |
file_name | string | Original filename |
headers | array | Column names from CSV header row |
sample_rows | array | First 5 rows of data for preview |
row_count | integer | Total number of rows (excluding header) |
auto_detected_identifiers | object | Columns that look like identifiers |
expires_at | timestamp | When the cached file expires |
Common Errors
| Status | Meaning | Solution |
|---|---|---|
| 400 | Bad Request | File missing or invalid CSV format |
| 413 | Payload Too Large | File exceeds 10 MB limit |
| 415 | Unsupported Media Type | File must be CSV |
POST /leads/import/start
Start an import job with field mappings.
Request
| Parameter | Type | Required | Description |
|---|---|---|---|
file_id | string | Yes | File ID from preview response |
primary_identifier | object | Yes | Primary identifier configuration |
primary_identifier.column | string | Yes | CSV column name for identifier |
primary_identifier.kind | string | Yes | Identifier type: "email", "phone", "cookie", "external_id", "social" |
field_mappings | object | No | Map CSV columns to profile fields |
alias_mappings | object | No | Map CSV columns to additional aliases |
Request Body Example
{
"file_id": "preview_abc123",
"primary_identifier": {
"column": "Email",
"kind": "email"
},
"field_mappings": {
"First Name": "first_name",
"Last Name": "last_name",
"Company": "company",
"Job Title": "title"
},
"alias_mappings": {
"Phone": "_alias_phone",
"LinkedIn": "_alias_social"
}
}
Alias Mapping Keys
Additional identifiers use _alias_ prefix:
_alias_email- Additional email address_alias_phone- Additional phone number_alias_cookie- Additional cookie ID_alias_external_id- Additional external ID_alias_social- Additional social handle
Response
202 Accepted
{
"job_id": "job_abc123",
"status": "queued",
"message": "Import job started",
"file_name": "leads.csv",
"total_rows": 1000
}
Request Example
curl -X POST "https://api.leadvibe.com/leads/import/start" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"file_id": "preview_abc123",
"primary_identifier": {
"column": "Email",
"kind": "email"
},
"field_mappings": {
"First Name": "first_name",
"Last Name": "last_name",
"Company": "company"
},
"alias_mappings": {
"Phone": "_alias_phone"
}
}'
Common Errors
| Status | Meaning | Solution |
|---|---|---|
| 400 | Bad Request | Missing required fields or invalid mappings |
| 404 | Not Found | File ID expired or not found (previews expire after 1 hour) |
GET /leads/import/jobs
List all import jobs for the current OU.
Request
| Parameter | Type | Required | Description |
|---|---|---|---|
page | integer | No | Page number (default: 1) |
limit | integer | No | Results per page (default: 25, max: 100) |
Response
200 OK
{
"jobs": [
{
"job_id": "job_abc123",
"status": "completed",
"file_name": "leads.csv",
"created_at": "2025-01-15T10:00:00Z",
"completed_at": "2025-01-15T10:05:00Z",
"total_rows": 1000,
"created_count": 750,
"updated_count": 230,
"failed_count": 20
},
{
"job_id": "job_def456",
"status": "in_progress",
"file_name": "contacts.csv",
"created_at": "2025-01-15T11:00:00Z",
"completed_at": null,
"total_rows": 500,
"created_count": 250,
"updated_count": 100,
"failed_count": 5
}
],
"total": 2,
"page": 1,
"limit": 25
}
Job Status Values
| Status | Description |
|---|---|
queued | Job is waiting to start |
in_progress | Currently processing rows |
completed | All rows processed |
failed | Job failed to complete |
cancelled | User cancelled the job |
Request Example
curl -X GET "https://api.leadvibe.com/leads/import/jobs?page=1&limit=25" \
-H "Authorization: Bearer <token>"
GET /leads/import/jobs/{jobId}
Get detailed results for a specific import job.
Request
| Parameter | Type | Required | Description |
|---|---|---|---|
jobId | string | Yes | Import job ID (path parameter) |
Response
200 OK
{
"job_id": "job_abc123",
"status": "completed",
"created_at": "2025-01-15T10:00:00Z",
"started_at": "2025-01-15T10:00:05Z",
"completed_at": "2025-01-15T10:05:00Z",
"file_name": "leads.csv",
"total_rows": 1000,
"created_count": 750,
"updated_count": 230,
"failed_count": 20,
"primary_identifier": {
"column": "Email",
"kind": "email"
},
"field_mappings": {
"First Name": "first_name",
"Last Name": "last_name",
"Company": "company"
},
"errors": [
{
"row": 45,
"error": "Invalid email format",
"value": "not-an-email"
},
{
"row": 102,
"error": "Missing required identifier",
"value": ""
}
]
}
Response Fields
| Field | Type | Description |
|---|---|---|
job_id | string | Job identifier |
status | string | Current status |
created_at | timestamp | When job was created |
started_at | timestamp | When processing began |
completed_at | timestamp | When processing finished (null if in progress) |
file_name | string | Original filename |
total_rows | integer | Total rows in CSV (excluding header) |
created_count | integer | Number of new leads created |
updated_count | integer | Number of existing leads updated |
failed_count | integer | Number of rows that failed |
primary_identifier | object | Identifier configuration used |
field_mappings | object | Field mappings used |
errors | array | Details for failed rows |
Request Example
curl -X GET "https://api.leadvibe.com/leads/import/jobs/job_abc123" \
-H "Authorization: Bearer <token>"
Common Errors
| Status | Meaning | Solution |
|---|---|---|
| 404 | Not Found | Job ID does not exist or not accessible |
Import Behavior Details
Deduplication
LeadVibe automatically prevents duplicate leads:
- Identifier Lookup: For each row, looks up lead by primary identifier
- Create or Update:
- If no matching lead exists: Creates new lead
- If matching lead exists: Updates profile with new values
- Alias Addition: Additional aliases are added to existing leads (not replaced)
Example:
- CSV Row: email=jane@example.com, phone=555-0100
- Existing Lead: email=jane@example.com, phone=555-0200
- Result: Lead now has both phone numbers as aliases
Field Mapping Rules
Profile Fields:
- Empty CSV cells are skipped (won't overwrite existing data)
- Non-empty values update the profile field
- Unknown field names are ignored
Alias Mappings:
- Aliases are added (not replaced)
- Duplicate aliases are ignored
- Empty alias values are skipped
Data Types:
- All profile fields stored as strings
- No automatic type conversion
- Validation performed on identifiers (e.g., email format)
Error Handling
Row-Level Errors:
- Failed rows don't stop the import
- Other rows continue processing
- Errors recorded with row number and reason
Common Error Types:
| Error | Cause |
|---|---|
| Invalid email format | Email doesn't match pattern |
| Invalid phone format | Phone contains invalid characters |
| Missing required identifier | Identifier column is empty |
| Database error | Unexpected storage failure |
Use Cases
Migrate Contacts from Another System
Import your existing contact database into LeadVibe.
# Step 1: Preview the CSV
curl -X POST "https://api.leadvibe.com/leads/import/preview" \
-H "Authorization: Bearer <token>" \
-F "file=@contacts.csv"
# Response includes file_id: "preview_abc123"
# Step 2: Start import with mappings
curl -X POST "https://api.leadvibe.com/leads/import/start" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"file_id": "preview_abc123",
"primary_identifier": {
"column": "Email",
"kind": "email"
},
"field_mappings": {
"FirstName": "first_name",
"LastName": "last_name",
"Company": "company",
"Title": "title"
}
}'
# Step 3: Monitor progress
curl -X GET "https://api.leadvibe.com/leads/import/jobs/job_abc123" \
-H "Authorization: Bearer <token>"
Import Event Leads with Multiple Identifiers
Import trade show leads with both email and phone numbers.
curl -X POST "https://api.leadvibe.com/leads/import/start" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"file_id": "preview_xyz789",
"primary_identifier": {
"column": "Email",
"kind": "email"
},
"field_mappings": {
"Name": "first_name",
"Company": "company",
"Booth Notes": "notes"
},
"alias_mappings": {
"Mobile": "_alias_phone",
"Badge ID": "_alias_external_id"
}
}'
Bulk Update Existing Leads
Update profile information for existing leads.
# Import with email as primary identifier
# Existing leads will be updated with new field values
curl -X POST "https://api.leadvibe.com/leads/import/start" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"file_id": "preview_update123",
"primary_identifier": {
"column": "Email",
"kind": "email"
},
"field_mappings": {
"Updated Title": "title",
"Current Company": "company"
}
}'
Notes
- CSV files must have a header row with column names
- Maximum file size: 10 MB
- File previews are cached for 1 hour (then must be re-uploaded)
- Imports run as background jobs (non-blocking)
- Large imports (10,000+ rows) may take several minutes
- Import jobs are OU-scoped (only visible within the OU)
- Empty CSV cells don't overwrite existing lead data
- UTF-8 encoding recommended for special characters
- Profile field names are case-insensitive in mappings