Reference
Imports
Bulk-load contacts, leads, or companies from CSV/XLSX files. The flow is
asynchronous: store enqueues a ProcessImport job and returns immediately
with status pending. Poll status for progress; fetch the error CSV via
downloadErrors once finished.
List imports
Returns paginated import jobs owned by the authenticated user, newest first.
GET
/api/imports
Query parameters
-
per_pageintegerRows per page. Default 20, maximum 100. See Lists, paging and filters.
Example:
20
curl --request GET \
--get "https://klozzo.com/api/imports?per_page=20" \
--header "Authorization: Bearer {YOUR_API_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"https://klozzo.com/api/imports"
);
const params = {
"per_page": "20",
};
Object.keys(params)
.forEach(key => url.searchParams.append(key, params[key]));
const headers = {
"Authorization": "Bearer {YOUR_API_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://klozzo.com/api/imports';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_API_TOKEN}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
'query' => [
'per_page' => '20',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'https://klozzo.com/api/imports'
params = {
'per_page': '20',
}
headers = {
'Authorization': 'Bearer {YOUR_API_TOKEN}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers, params=params)
response.json()
{
"data": [
{
"id": null,
"type": "contacts",
"file_name": "adipisci.csv",
"status": "pending",
"total_rows": 0,
"processed_rows": 0,
"succeeded_rows": null,
"failed_rows": 0,
"column_mapping": null,
"duplicate_handling": "skip",
"errors": null,
"error_file_available": false,
"progress_percentage": 0,
"started_at": null,
"finished_at": null,
"completed_at": null,
"created_at": null,
"updated_at": null
},
{
"id": null,
"type": "contacts",
"file_name": "fugit.csv",
"status": "pending",
"total_rows": 0,
"processed_rows": 0,
"succeeded_rows": null,
"failed_rows": 0,
"column_mapping": null,
"duplicate_handling": "skip",
"errors": null,
"error_file_available": false,
"progress_percentage": 0,
"started_at": null,
"finished_at": null,
"completed_at": null,
"created_at": null,
"updated_at": null
}
],
"links": {
"first": "/?page=1",
"last": "/?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"links": [
{
"url": null,
"label": "« Previous",
"page": null,
"active": false
},
{
"url": "/?page=1",
"label": "1",
"page": 1,
"active": true
},
{
"url": null,
"label": "Next »",
"page": null,
"active": false
}
],
"path": "/",
"per_page": 20,
"to": 2,
"total": 2
}
}
-
dataobject[]-
idstring -
typestring -
file_namestring -
statusstring -
total_rowsinteger -
processed_rowsinteger -
succeeded_rowsstring -
failed_rowsinteger -
column_mappingstring -
duplicate_handlingstring -
errorsstring -
error_file_availableboolean -
progress_percentageinteger -
started_atstring -
finished_atstring -
completed_atstring -
created_atstring -
updated_atstring
-
-
linksobject-
firststring -
laststring -
prevstring -
nextstring
-
-
metaobject-
current_pageinteger -
frominteger -
last_pageinteger -
linksobject[]-
urlstring -
labelstring -
pagestring -
activeboolean
-
-
pathstring -
per_pageinteger -
tointeger -
totalinteger
-
Create an import
Creates an import: uploads a CSV/XLSX file of contacts and queues it for
processing. Must be sent as
multipart/form-data. Returns immediately with status=pending; poll
GET /api/imports/{id}/status for progress.
POST
/api/imports
Body parameters
-
typestring requiredWhat to import. One of
contacts,leads,companies.Example:
contacts -
filestring requiredCSV, TXT, XLSX, or XLS. Max 10 MB.
-
column_mappingobjectMap of
csv_column_name => contact_field_name. Required for non-conventional headers.Example:
[] -
duplicate_handlingstringAction on collision. One of
skip(default),update,create.Example:
skip -
location_idintegerScope the import to a specific location.
Example:
1
curl --request POST \
"https://klozzo.com/api/imports" \
--header "Authorization: Bearer {YOUR_API_TOKEN}" \
--header "Content-Type: multipart/form-data" \
--header "Accept: application/json" \
--form "type=contacts"\
--form "duplicate_handling=skip"\
--form "location_id=1"\
--form "file=@/private/var/folders/yw/tssyhl110hs29p29scc2m0jc0000gn/T/phpi0k13cg52dh7d0QJtkp"
const url = new URL(
"https://klozzo.com/api/imports"
);
const headers = {
"Authorization": "Bearer {YOUR_API_TOKEN}",
"Content-Type": "multipart/form-data",
"Accept": "application/json",
};
const body = new FormData();
body.append('type', 'contacts');
body.append('duplicate_handling', 'skip');
body.append('location_id', '1');
body.append('file', document.querySelector('input[name="file"]').files[0]);
fetch(url, {
method: "POST",
headers,
body,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://klozzo.com/api/imports';
$response = $client->post(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_API_TOKEN}',
'Content-Type' => 'multipart/form-data',
'Accept' => 'application/json',
],
'multipart' => [
[
'name' => 'type',
'contents' => 'contacts'
],
[
'name' => 'duplicate_handling',
'contents' => 'skip'
],
[
'name' => 'location_id',
'contents' => '1'
],
[
'name' => 'file',
'contents' => fopen('/private/var/folders/yw/tssyhl110hs29p29scc2m0jc0000gn/T/phpi0k13cg52dh7d0QJtkp', 'r')
],
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'https://klozzo.com/api/imports'
files = {
'type': (None, 'contacts'),
'duplicate_handling': (None, 'skip'),
'location_id': (None, '1'),
'file': open('/private/var/folders/yw/tssyhl110hs29p29scc2m0jc0000gn/T/phpi0k13cg52dh7d0QJtkp', 'rb')}
payload = {
"type": "contacts",
"column_mapping": [],
"duplicate_handling": "skip",
"location_id": 1
}
headers = {
'Authorization': 'Bearer {YOUR_API_TOKEN}',
'Content-Type': 'multipart/form-data',
'Accept': 'application/json'
}
response = requests.request('POST', url, headers=headers, files=files)
response.json()
{
"data": {
"id": null,
"type": "contacts",
"file_name": "eius.csv",
"status": "pending",
"total_rows": 0,
"processed_rows": 0,
"succeeded_rows": null,
"failed_rows": 0,
"column_mapping": null,
"duplicate_handling": "skip",
"errors": null,
"error_file_available": false,
"progress_percentage": 0,
"started_at": null,
"finished_at": null,
"completed_at": null,
"created_at": null,
"updated_at": null
}
}
-
dataobject-
idstring -
typestring -
file_namestring -
statusstring -
total_rowsinteger -
processed_rowsinteger -
succeeded_rowsstring -
failed_rowsinteger -
column_mappingstring -
duplicate_handlingstring -
errorsstring -
error_file_availableboolean -
progress_percentageinteger -
started_atstring -
finished_atstring -
completed_atstring -
created_atstring -
updated_atstring
-
{
"message": "File debe ser un archivo de tipo: csv, txt, xlsx, xls.",
"errors": {
"file": [
"File debe ser un archivo de tipo: csv, txt, xlsx, xls."
]
}
}
Every error shares the same shape — message and errors.
See Errors.
{
"message": "File no puede pesar más de 10240 kilobytes.",
"errors": {
"file": [
"File no puede pesar más de 10240 kilobytes."
]
}
}
Every error shares the same shape — message and errors.
See Errors.
{
"message": "Falta type.",
"errors": {
"type": [
"Falta type."
]
}
}
Every error shares the same shape — message and errors.
See Errors.
Fetch an import
Returns one import by id, with its full payload and the original column
mapping. For lightweight progress
polling, prefer status instead.
GET
/api/imports/{id}
Path parameters
-
idinteger requiredImport ID.
Example:
17
curl --request GET \
--get "https://klozzo.com/api/imports/17" \
--header "Authorization: Bearer {YOUR_API_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"https://klozzo.com/api/imports/17"
);
const headers = {
"Authorization": "Bearer {YOUR_API_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://klozzo.com/api/imports/17';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_API_TOKEN}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'https://klozzo.com/api/imports/17'
headers = {
'Authorization': 'Bearer {YOUR_API_TOKEN}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()
{
"data": {
"id": null,
"type": "contacts",
"file_name": "adipisci.csv",
"status": "pending",
"total_rows": 0,
"processed_rows": 0,
"succeeded_rows": null,
"failed_rows": 0,
"column_mapping": null,
"duplicate_handling": "skip",
"errors": null,
"error_file_available": false,
"progress_percentage": 0,
"started_at": null,
"finished_at": null,
"completed_at": null,
"created_at": null,
"updated_at": null
}
}
-
dataobject-
idstring -
typestring -
file_namestring -
statusstring -
total_rowsinteger -
processed_rowsinteger -
succeeded_rowsstring -
failed_rowsinteger -
column_mappingstring -
duplicate_handlingstring -
errorsstring -
error_file_availableboolean -
progress_percentageinteger -
started_atstring -
finished_atstring -
completed_atstring -
created_atstring -
updated_atstring
-
Delete an import
Removes the import record and original upload from disk. Imported contacts are NOT removed.
DELETE
/api/imports/{id}
Path parameters
-
idinteger requiredImport ID.
Example:
17
curl --request DELETE \
"https://klozzo.com/api/imports/17" \
--header "Authorization: Bearer {YOUR_API_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"https://klozzo.com/api/imports/17"
);
const headers = {
"Authorization": "Bearer {YOUR_API_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://klozzo.com/api/imports/17';
$response = $client->delete(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_API_TOKEN}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'https://klozzo.com/api/imports/17'
headers = {
'Authorization': 'Bearer {YOUR_API_TOKEN}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('DELETE', url, headers=headers)
response.json()
{
"message": "Import deleted."
}
-
messagestring
Import progress
Returns the progress of one import in about a kilobyte, meant for polling.
Call every 2–5 s
until status is completed or failed.
GET
/api/imports/{import_id}/status
Path parameters
-
import_idinteger requiredImport ID.
Example:
17
curl --request GET \
--get "https://klozzo.com/api/imports/17/status" \
--header "Authorization: Bearer {YOUR_API_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"https://klozzo.com/api/imports/17/status"
);
const headers = {
"Authorization": "Bearer {YOUR_API_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://klozzo.com/api/imports/17/status';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_API_TOKEN}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'https://klozzo.com/api/imports/17/status'
headers = {
'Authorization': 'Bearer {YOUR_API_TOKEN}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()
{
"id": 17,
"status": "processing",
"total_rows": 1500,
"processed_rows": 420,
"succeeded_rows": 415,
"failed_rows": 5,
"progress_percentage": 28,
"errors": null,
"error_file_available": false,
"started_at": "2026-06-05T13:42:00+00:00",
"finished_at": null,
"completed_at": null
}
-
idinteger -
statusstring -
total_rowsinteger -
processed_rowsinteger -
succeeded_rowsinteger -
failed_rowsinteger -
progress_percentageinteger -
errorsstring -
error_file_availableboolean -
started_atstring -
finished_atstring -
completed_atstring
Download error CSV
Streams a CSV containing the rows that failed validation, with an error
column appended. Available only when error_file_available=true in the
status response.
GET
/api/imports/{import_id}/errors
Path parameters
-
import_idinteger requiredImport ID.
Example:
17
curl --request GET \
--get "https://klozzo.com/api/imports/17/errors" \
--header "Authorization: Bearer {YOUR_API_TOKEN}" \
--header "Content-Type: application/json" \
--header "Accept: application/json"
const url = new URL(
"https://klozzo.com/api/imports/17/errors"
);
const headers = {
"Authorization": "Bearer {YOUR_API_TOKEN}",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());
$client = new \GuzzleHttp\Client();
$url = 'https://klozzo.com/api/imports/17/errors';
$response = $client->get(
$url,
[
'headers' => [
'Authorization' => 'Bearer {YOUR_API_TOKEN}',
'Content-Type' => 'application/json',
'Accept' => 'application/json',
],
]
);
$body = $response->getBody();
print_r(json_decode((string) $body));
import requests
import json
url = 'https://klozzo.com/api/imports/17/errors'
headers = {
'Authorization': 'Bearer {YOUR_API_TOKEN}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request('GET', url, headers=headers)
response.json()
"<binary CSV>"
This response has no body.
{
"message": "No error file"
}
Every error shares the same shape — message and errors.
See Errors.