Import leads from CSV
Upload a CSV file to bulk import leads. Supports:
- Auto-detection of column mappings (email, firstName, lastName, company, jobTitle, phone, linkedinUrl, city, state, country, timezone, notes, etc.)
- Custom mapping via the
mappingfield for non-standard column names - Data cleanup (default on): normalizes emails, phone numbers, LinkedIn URLs, strips special chars
- Deduplication (default on): skips leads that already exist by email. Set to false to update existing leads.
- Unrecognized columns are stored as custom fields on the lead
- Maximum 50,000 rows per file, 50 MB file size limit
- Processed in batches of 1,000 with up to 10 concurrent batches
curl -X POST "https://api.sendkit.ai/v1/leads/import/csv" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
--form file=example_string \
--form mapping=example_string \
--form skipDuplicates=true \
--form dataCleanup=true \
--form tag=example_string
import requests
import json
url = "https://api.sendkit.ai/v1/leads/import/csv"
headers = {
"X-Api-Key": "YOUR_API_KEY",
"Authorization": "Bearer YOUR_API_TOKEN"
}
data = {
"file": "example_string",
"mapping": "example_string",
"skipDuplicates": "true",
"dataCleanup": "true",
"tag": "example_string"
}
response = requests.post(url, headers=headers, data=data)
print(response.json())
const formData = new FormData();
formData.append("file", "example_string");
formData.append("mapping", "example_string");
formData.append("skipDuplicates", "true");
formData.append("dataCleanup", "true");
formData.append("tag", "example_string");
const response = await fetch("https://api.sendkit.ai/v1/leads/import/csv", {
method: "POST",
headers: {
"X-Api-Key": "YOUR_API_KEY",
"Authorization": "Bearer YOUR_API_TOKEN"
},
body: formData
});
const data = await response.json();
console.log(data);
package main
import (
"fmt"
"net/http"
"bytes"
"mime/multipart"
)
func main() {
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
writer.WriteField("file", "example_string")
writer.WriteField("mapping", "example_string")
writer.WriteField("skipDuplicates", "true")
writer.WriteField("dataCleanup", "true")
writer.WriteField("tag", "example_string")
writer.Close()
req, err := http.NewRequest("POST", "https://api.sendkit.ai/v1/leads/import/csv", body)
if err != nil {
panic(err)
}
req.Header.Set("X-Api-Key", "YOUR_API_KEY")
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
req.Header.Set("Content-Type", writer.FormDataContentType())
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Response Status:", resp.Status)
}
require 'net/http'
require 'json'
uri = URI('https://api.sendkit.ai/v1/leads/import/csv')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request['X-Api-Key'] = 'YOUR_API_KEY'
request['Authorization'] = 'Bearer YOUR_API_TOKEN'
request.set_form([
["file", "example_string"],
["mapping", "example_string"],
["skipDuplicates", "true"],
["dataCleanup", "true"],
["tag", "example_string"]
], 'multipart/form-data')
response = http.request(request)
puts response.body
{
"success": true,
"data": {
"imported": 180,
"updated": 0,
"skipped": 15,
"failed": 5,
"importedLeadIds": [
"665d4e5f6a7b8c9d0e1f2a3b"
],
"errors": [
{
"email": "not-an-email",
"error": "Invalid email format"
}
],
"csvInfo": {
"totalRows": 200,
"columns": [
"Email",
"First Name",
"Last Name",
"Company",
"Title",
"Industry"
],
"mapping": {
"Email": "email",
"First Name": "firstName",
"Last Name": "lastName",
"Company": "companyName",
"Title": "jobTitle",
"Industry": "custom:Industry"
}
}
}
}
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "CSV file is required. Send as multipart/form-data with field name "file"."
}
}
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "CSV file is empty"
}
}
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Maximum 50,000 leads per CSV file"
}
}
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "No email column detected. Provide a "mapping" field or ensure your CSV has an "email" column."
}
}
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid mapping JSON"
}
}
/v1/leads/import/csv
Platform API key (sk_user_...) or Workspace API key (sk_...)
The media type of the request body
CSV file with headers. Must contain an email column.
JSON string mapping CSV column headers to lead fields.
Example: {"Email Address": "email", "First": "firstName", "Company": "companyName"}
If omitted, columns are auto-detected from common header aliases.
Use "skip" to ignore a column. Unmapped columns become custom fields.
Skip leads whose email already exists (false = update existing)
Normalize emails, phone numbers, names
Tag to apply to all imported leads
Request Preview
Response
Response will appear here after sending the request
Authentication
API Key for authentication. Platform API key (sk_user_...) or Workspace API key (sk_...)
Bearer token. API key as Bearer token
Body
CSV file with headers. Must contain an email column.
JSON string mapping CSV column headers to lead fields.
Example: \\{"Email Address": "email", "First": "firstName", "Company": "companyName"\\}
If omitted, columns are auto-detected from common header aliases.
Use "skip" to ignore a column. Unmapped columns become custom fields.
Skip leads whose email already exists (false = update existing)
truefalseTag to apply to all imported leads
Responses
Last updated today
Built with Documentation.AI