Import leads from CSV into campaign
Upload a CSV file to create leads and add them to the campaign in a single operation.
- Maximum file size: 50 MB
- Maximum rows: 50,000
- Automatically detects email, firstName, lastName, companyName, jobTitle columns by common aliases
- Unrecognized columns are stored as custom fields on the lead
- Existing leads (by email) are reused, not duplicated
- Duplicate campaign leads are skipped
- Processes in batches of 1,000 for performance
curl -X POST "https://api.sendkit.ai/v1/campaigns/example_string/leads/import/csv" \
-H "X-Api-Key: YOUR_API_KEY" \
--form file=example_string
import requests
import json
url = "https://api.sendkit.ai/v1/campaigns/example_string/leads/import/csv"
headers = {
"X-Api-Key": "YOUR_API_KEY"
}
data = {
"file": "example_string"
}
response = requests.post(url, headers=headers, data=data)
print(response.json())
const formData = new FormData();
formData.append("file", "example_string");
const response = await fetch("https://api.sendkit.ai/v1/campaigns/example_string/leads/import/csv", {
method: "POST",
headers: {
"X-Api-Key": "YOUR_API_KEY"
},
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.Close()
req, err := http.NewRequest("POST", "https://api.sendkit.ai/v1/campaigns/example_string/leads/import/csv", body)
if err != nil {
panic(err)
}
req.Header.Set("X-Api-Key", "YOUR_API_KEY")
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/campaigns/example_string/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.set_form([
["file", "example_string"]
], 'multipart/form-data')
response = http.request(request)
puts response.body
{
"success": true,
"data": {
"leads": {
"created": 180,
"existing": 15,
"failed": 5
},
"campaign": {
"added": 190,
"skipped": 5
},
"totalRows": 200,
"errors": [
{
"email": "not-an-email",
"error": "Invalid email"
}
]
}
}
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "CSV file is required"
}
}
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "CSV file is empty"
}
}
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Maximum 50,000 leads per CSV"
}
}
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "No email column detected"
}
}
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Campaign not found"
}
}
/v1/campaigns/{campaignId}/leads/import/csvPlatform API key (sk_user_...) or Workspace API key (sk_...)
Campaign ID
The media type of the request body
CSV file with headers. Must contain an email column.
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_...)
Path Parameters
Campaign ID
Body
CSV file with headers. Must contain an email column.
Responses
Lead creation summary
New leads created
Existing leads matched by email
Rows that failed (invalid email, etc.)
Campaign addition summary
Leads newly added to campaign
Leads already in campaign (skipped)
Total rows parsed from CSV
First 50 row-level errors (omitted if none)
Missing file, empty CSV, too many rows, or no email column
Campaign not found
Last updated today
Built with Documentation.AI