Upload and validate a CSV file for bulk reseller import. Returns a row-by-row report
with a verdict per row (valid / error / warning), separating blocking errors[]
from non-blocking warnings[]. Validated data is stored in a temporary session
(30 min TTL) keyed by import_id, which must be passed to /resellers/import/confirm
to actually create or update the resellers.
CSV format
- Columns (in any order):
company_name,description,vat_number,address,city,main_contact,email,phone,language,notes. - Required:
company_name,vat_number. All other columns are optional. phone, when present, must include the leading+CCcountry prefix (e.g.+39 02 1234567). Bare local numbers are rejected withinvalid_format.languageacceptsitoren(defaults toitwhen empty).- The first data row is row
2. - Standard CSV (RFC 4180) — fields containing commas, quotes or newlines must be
double-quoted (
"note, with comma"). Spreadsheet tools auto-quote on save.
Row outcomes
| status | What it means | Confirm action |
|---|---|---|
valid |
All checks passed | CREATE |
error |
At least one blocking error in errors[] (required, invalid_format, too_long, duplicate_in_csv, archived, …) |
always skipped |
warning |
A reseller with the same vat already exists in the database (in warnings[]) |
UPDATE if override: true, else skipped |
Reseller imports cannot produce ambiguous rows — that status only applies to user imports.
Limits — max 10 MB, max 1000 rows. Larger files return 400.
POST
/resellers/import/validate
curl \
--request POST 'https://collect.your-domain.com/api/resellers/import/validate' \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header "Content-Type: multipart/form-data" \
--form "file=@file"
Response examples (200)
{
"code": 200,
"message": "resellers import validated",
"data": {
"import_id": "3312b187-a8b0-45f5-b23a-98798b64eb31",
"total_rows": 6,
"valid_rows": 2,
"error_rows": 2,
"warning_rows": 1,
"ambiguous_rows": 1,
"rows": [
{
"row_number": 2,
"status": "valid",
"data": {
"email": "marco.rossi@nethesis.it",
"name": "Marco Rossi",
"phone": "+39 333 1234567",
"company_name": "Acme Corp",
"organization_id": "zm45rltjc9rr",
"roles": "Admin",
"role_ids": [
"7jmz7ryag1m254m4428n8"
]
}
},
{
"row_number": 3,
"status": "valid",
"data": {
"email": "support@beta.it",
"name": "Beta Support",
"phone": "",
"company_name": "Beta Solutions",
"organization_id": "jl6lgn3l6nsi",
"roles": "Support",
"role_ids": [
"77evvdf876ze8oykdk4y9"
]
}
},
{
"row_number": 4,
"status": "error",
"data": {
"email": "not-an-email",
"name": "Bad Email",
"phone": "+39 333 0000000",
"company_name": "Acme Corp",
"organization_id": "",
"roles": "Admin",
"role_ids": [
"7jmz7ryag1m254m4428n8"
]
},
"errors": [
{
"field": "email",
"message": "invalid_format",
"values": [
"not-an-email"
]
}
]
},
{
"row_number": 5,
"status": "error",
"data": {
"email": "test@nethesis.it",
"name": "Wrong Org",
"phone": "",
"company_name": "Organization That Does Not Exist",
"organization_id": "",
"roles": "Support",
"role_ids": [
"77evvdf876ze8oykdk4y9"
]
},
"errors": [
{
"field": "company_name",
"message": "not_found",
"values": [
"Organization That Does Not Exist"
]
}
]
},
{
"row_number": 6,
"status": "warning",
"data": {
"email": "edoardo.spadoni@nethesis.it",
"name": "Mario Rossi",
"phone": "",
"company_name": "Acme Corp",
"organization_id": "zm45rltjc9rr",
"roles": "Admin",
"role_ids": [
"7jmz7ryag1m254m4428n8"
]
},
"warnings": [
{
"field": "email",
"message": "already_exists",
"values": [
"edoardo.spadoni@nethesis.it"
]
}
]
},
{
"row_number": 7,
"status": "ambiguous",
"data": {
"email": "ambig@nethesis.it",
"name": "Ambiguous Org",
"phone": "",
"company_name": "Gamma",
"organization_id": "",
"roles": "Support",
"role_ids": [
"77evvdf876ze8oykdk4y9"
]
},
"errors": [
{
"field": "company_name",
"message": "ambiguous",
"values": [
"Gamma"
],
"candidates": [
{
"logto_id": "abc123",
"name": "Gamma Tech",
"type": "distributor"
},
{
"logto_id": "def456",
"name": "Gamma Group",
"type": "customer"
}
]
}
]
}
]
}
}
Response examples (400)
{
"code": 400,
"message": "validation failed",
"data": {
"type": "validation_error",
"errors": [
{
"key": "username",
"message": "required",
"value": "string"
}
]
}
}
Response examples (401)
{
"code": 401,
"message": "invalid token",
"data": {}
}
Response examples (403)
{
"code": 403,
"message": "insufficient permissions",
"data": {}
}