Skip to the content

Batches

Classify a file of products - upload an .xlsx or .csv file, choose the columns, start it, follow its progress and download the results.

A batch classifies every row of a spreadsheet. The flow has five steps:

  1. Upload the file (POST /api/batches). The answer lists the columns found, a suggested mapping and a preview. Nothing is classified yet.
  2. Optionally check the rows with your column mapping (POST /api/batches/{batch_id}/validate).
  3. Start it (POST /api/batches/{batch_id}/start) with the column mapping. The start can answer 402 when the account cannot be charged for the rows.
  4. Poll GET /api/batches/{batch_id}/progress until the status is completed or completed_with_errors, or wait for the batch.completed webhook (Asynchronous work).
  5. Read the rows (GET /api/batches/{batch_id}/rows) or download the results as Excel (GET /api/batches/{batch_id}/export).

Each row that is classified becomes a lookup of the kind batch (Lookups) and can be charged (Rate limits and quotas). Rows send no lookup.completed event: the batch sends batch.completed when it is done. Batches need the plan feature feature.batch, and the number of rows is limited by the plan (Rate limits and quotas).

The file

An .xlsx or .csv file whose first row holds the column names. GET /api/batches/template gives a file to start from, with the columns description, material, use, composition, origin, notes, sku and hts_code. Your own column names work too: the column mapping says which column holds which field. Only description is required.

Mapping field Column that holds
description The product description. Required
material, use, composition, origin, notes The same fields as on a lookup
sku Your SKU code. Needed for save_to_catalog
existing_code The code in use today. It is checked against the tariff schedule and compared with the suggestion

The batch object

Field Type Meaning
id string The id of the batch
created_at, updated_at string ISO 8601, UTC
filename string The name of the uploaded file
status string uploaded, queued, running, completed, completed_with_errors or error
columns array The column names found in the file
column_mapping object The mapping the batch was started with
market, dataset_version string The market and tariff version of the batch
validation object The suggested mapping and the result of the row check
total_rows, processed_rows, failed_rows integer Counters
counts object Rows per row status
error string or null The message of a batch that failed as a whole
save_to_catalog boolean Whether rows are saved to the SKU catalog
preview array The first rows of the file: after an upload, and on GET /api/batches/{batch_id} with preview=true

The row object

Field Type Meaning
row_index integer The row number in the file. The first data row is 2
raw object The cells of the row, by column name
status string pending, processing, done, error, skipped or duplicate (the same product as an earlier row, named in duplicate_of, whose result it reuses)
issues array What the row check found
duplicate_of integer or null The row_index it duplicates
lookup_id string or null The lookup of the row
attempts integer How often it was tried
error string or null Why it failed
result_status, recommended_code, confidence - The outcome of the lookup
code_check object The check of the existing code, when a column was mapped to existing_code
final_code string or null The reviewer's code, once decided

GET /api/batches/template

An .xlsx file with the columns description, material, use, composition, origin, notes, sku and hts_code, example rows and a guide sheet.

Returns 200 with a file (application/vnd.openxmlformats-officedocument.spreadsheetml.sheet).

Errors: 401 No valid API key was sent; 403 The role of the key, or the plan of the account, does not allow this call; 422 The request is not valid; 500 An unexpected failure.

Try it in the explorer

GET /api/batches/template
curl "https://htspilot.com/api/batches/template" \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME" \
  -o "hts_lookup_template.xlsx"
import json
import os
import urllib.request

request = urllib.request.Request(
    "https://htspilot.com/api/batches/template",
    headers={"X-API-Key": os.environ["HTS_PILOT_API_KEY"]},
    method="GET",
)
with urllib.request.urlopen(request) as response, open("hts_lookup_template.xlsx", "wb") as out:
    out.write(response.read())
import { writeFile } from "node:fs/promises";

const response = await fetch("https://htspilot.com/api/batches/template", {
  headers: { "X-API-Key": process.env.HTS_PILOT_API_KEY },
});
await writeFile("hts_lookup_template.xlsx", Buffer.from(await response.arrayBuffer()));
Response 200
{
  "file": true,
  "content_type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  "content_disposition": "attachment; filename=\"hts_lookup_template.xlsx\"",
  "bytes": 11735
}

Upload a file

POST /api/batches

Changes data in your account when executed. Send the file as multipart/form-data in the field file. The first row holds the column names; GET /api/batches/template gives a file to start from. The answer lists the columns found, a suggested mapping and a preview; nothing is classified until the batch is started.

Request body (multipart/form-data)

Name Type Required Description
file file Yes -

Returns 200 with BatchOut.

Errors: 401 No valid API key was sent; 403 The role of the key, or the plan of the account, does not allow this call; 422 The request is not valid; 500 An unexpected failure.

Try it in the explorer

curl -X POST https://htspilot.com/api/batches \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME" \
  -F "file=@products.csv"
POST /api/batches
curl -X POST "https://htspilot.com/api/batches" \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME" \
  -F "file=@products.csv"
import json
import os
import urllib.request

boundary = "hts-pilot-example"
data = b""
for field, name in [["file", "products.csv"]]:
    with open(name, "rb") as f:
        data += (f"--{boundary}\r\nContent-Disposition: form-data; name=\"{field}\"; filename=\"{name}\"\r\n"
                 "Content-Type: application/octet-stream\r\n\r\n").encode() + f.read() + b"\r\n"
data += f"--{boundary}--\r\n".encode()

request = urllib.request.Request(
    "https://htspilot.com/api/batches",
    data=data,
    headers={"X-API-Key": os.environ["HTS_PILOT_API_KEY"], "Content-Type": f"multipart/form-data; boundary={boundary}"},
    method="POST",
)
with urllib.request.urlopen(request) as response:
    print(json.load(response))
import { readFile } from "node:fs/promises";

const form = new FormData();
form.append("file", new Blob([await readFile("products.csv")]), "products.csv");

const response = await fetch("https://htspilot.com/api/batches", {
  method: "POST",
  headers: { "X-API-Key": process.env.HTS_PILOT_API_KEY },
  body: form,
});
console.log(await response.json());
Response 200
{
  "id": "9058ee5650844af9b9d6f473bdf3c544",
  "created_at": "2026-10-03T16:07:51.820019Z",
  "updated_at": "2026-10-03T16:07:51.820019Z",
  "filename": "products.csv",
  "status": "uploaded",
  "columns": [
    "description",
    "material"
  ],
  "column_mapping": {
    "description": "description",
    "material": "material",
    "origin": "origin",
    "sku": "sku",
    "existing_code": "hts_code"
  },
  "market": "",
  "dataset_version": null,
  "validation": {
    "suggested_mapping": {
      "description": "description",
      "material": "material",
      "origin": "origin",
      "sku": "sku",
      "existing_code": "hts_code"
    },
    "precheck": {
      "total": 3,
      "empty": 0,
      "examples": 0,
      "invalid": 0,
      "duplicates": 0,
      "valid": 3,
      "warnings": 0,
      "issues": []
    }
  },
  "total_rows": 3,
  "processed_rows": 0,
  "failed_rows": 0,
  "error": null,
  "save_to_catalog": false,
  "counts": {
    "pending": 3
  },
  "preview": [
    {
      "row_index": 2,
      "description": "Men's T-shirt, knitted, 100% cotton, short sleeves",
      "material": "cotton",
      "origin": "VN",
      "sku": "EXAMPLE-TSH-001",
      "hts_code": "6109.10.00.12"
    },
    {
      "row_index": 3,
      "description": "Cotton terry bath towel, 70 x 140 cm",
      "material": "cotton",
      "origin": "IN",
      "sku": "EXAMPLE-TWL-014",
      "hts_code": ""
    }
  ]
}

Check the rows

POST /api/batches/{batch_id}/validate

Changes data in your account when executed.

Path parameters

Name Type Description
batch_id string -

Request body (application/json)

Name Type Required Description
column_mapping ColumnMapping Yes -
market string No Up to 8 characters
tariff_version string or null No -
save_to_catalog boolean No Save/update the SKU in the shared catalog (requires a sku column). Default false

column_mapping: ColumnMapping

Name Type Required Description
description string Yes -
material string or null No -
use string or null No -
composition string or null No -
origin string or null No -
notes string or null No -
sku string or null No -
existing_code string or null No Column with the HTS code currently in use: it is checked for validity and compared with the suggestion

Returns 200 with BatchOut.

Errors: 401 No valid API key was sent; 403 The role of the key, or the plan of the account, does not allow this call; 422 The request is not valid; 500 An unexpected failure.

Try it in the explorer

POST /api/batches/{batch_id}/validate
curl -X POST "https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544/validate" \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME" \
  -H "Content-Type: application/json" \
  -d '{
  "column_mapping": {
    "description": "description",
    "material": "material",
    "origin": "origin",
    "sku": "sku",
    "existing_code": "hts_code"
  },
  "market": "US",
  "save_to_catalog": false
}'
import json
import os
import urllib.request

request = urllib.request.Request(
    "https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544/validate",
    data=json.dumps({
        "column_mapping": {
            "description": "description",
            "material": "material",
            "origin": "origin",
            "sku": "sku",
            "existing_code": "hts_code",
        },
        "market": "US",
        "save_to_catalog": False,
    }).encode(),
    headers={"X-API-Key": os.environ["HTS_PILOT_API_KEY"], "Content-Type": "application/json"},
    method="POST",
)
with urllib.request.urlopen(request) as response:
    print(json.load(response))
const response = await fetch("https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544/validate", {
  method: "POST",
  headers: { "X-API-Key": process.env.HTS_PILOT_API_KEY, "Content-Type": "application/json" },
  body: JSON.stringify({
    "column_mapping": {
      "description": "description",
      "material": "material",
      "origin": "origin",
      "sku": "sku",
      "existing_code": "hts_code"
    },
    "market": "US",
    "save_to_catalog": false
  }),
});
console.log(await response.json());
Response 200
{
  "id": "9058ee5650844af9b9d6f473bdf3c544",
  "created_at": "2026-10-03T16:07:51.820019",
  "updated_at": "2026-10-03T16:07:51.820019",
  "filename": "products.csv",
  "status": "uploaded",
  "columns": [
    "description",
    "material"
  ],
  "column_mapping": {
    "description": "description",
    "material": "material",
    "origin": "origin",
    "sku": "sku",
    "existing_code": "hts_code"
  },
  "market": "",
  "dataset_version": null,
  "validation": {
    "suggested_mapping": {
      "description": "description",
      "material": "material",
      "origin": "origin",
      "sku": "sku",
      "existing_code": "hts_code"
    },
    "precheck": {
      "total": 3,
      "empty": 0,
      "examples": 0,
      "invalid": 0,
      "duplicates": 0,
      "valid": 3,
      "warnings": 0,
      "issues": []
    }
  },
  "total_rows": 3,
  "processed_rows": 0,
  "failed_rows": 0,
  "error": null,
  "save_to_catalog": false,
  "counts": {
    "pending": 3
  },
  "preview": [
    {
      "row_index": 2,
      "description": "Men's T-shirt, knitted, 100% cotton, short sleeves",
      "material": "cotton",
      "origin": "VN",
      "sku": "EXAMPLE-TSH-001",
      "hts_code": "6109.10.00.12"
    },
    {
      "row_index": 3,
      "description": "Cotton terry bath towel, 70 x 140 cm",
      "material": "cotton",
      "origin": "IN",
      "sku": "EXAMPLE-TWL-014",
      "hts_code": ""
    }
  ]
}

Start a batch

POST /api/batches/{batch_id}/start

Changes data in your account when executed. column_mapping names the column of the file for each field; only description is required. Spends credits for every row that is classified.

Path parameters

Name Type Description
batch_id string -

Request body (application/json)

Name Type Required Description
column_mapping ColumnMapping Yes -
market string No Up to 8 characters
tariff_version string or null No -
save_to_catalog boolean No Save/update the SKU in the shared catalog (requires a sku column). Default false

column_mapping: ColumnMapping

Name Type Required Description
description string Yes -
material string or null No -
use string or null No -
composition string or null No -
origin string or null No -
notes string or null No -
sku string or null No -
existing_code string or null No Column with the HTS code currently in use: it is checked for validity and compared with the suggestion

Returns 200 with BatchOut.

Errors: 401 No valid API key was sent; 403 The role of the key, or the plan of the account, does not allow this call; 422 The request is not valid; 500 An unexpected failure.

Try it in the explorer

A batch can be started once, from the status uploaded; a second start answers 409.

POST /api/batches/{batch_id}/start
curl -X POST "https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544/start" \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME" \
  -H "Content-Type: application/json" \
  -d '{
  "column_mapping": {
    "description": "description",
    "material": "material",
    "origin": "origin",
    "sku": "sku",
    "existing_code": "hts_code"
  },
  "market": "US",
  "save_to_catalog": false
}'
import json
import os
import urllib.request

request = urllib.request.Request(
    "https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544/start",
    data=json.dumps({
        "column_mapping": {
            "description": "description",
            "material": "material",
            "origin": "origin",
            "sku": "sku",
            "existing_code": "hts_code",
        },
        "market": "US",
        "save_to_catalog": False,
    }).encode(),
    headers={"X-API-Key": os.environ["HTS_PILOT_API_KEY"], "Content-Type": "application/json"},
    method="POST",
)
with urllib.request.urlopen(request) as response:
    print(json.load(response))
const response = await fetch("https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544/start", {
  method: "POST",
  headers: { "X-API-Key": process.env.HTS_PILOT_API_KEY, "Content-Type": "application/json" },
  body: JSON.stringify({
    "column_mapping": {
      "description": "description",
      "material": "material",
      "origin": "origin",
      "sku": "sku",
      "existing_code": "hts_code"
    },
    "market": "US",
    "save_to_catalog": false
  }),
});
console.log(await response.json());
Response 200
{
  "id": "9058ee5650844af9b9d6f473bdf3c544",
  "created_at": "2026-10-03T16:07:51.820019",
  "updated_at": "2026-10-03T16:07:51.835161Z",
  "filename": "products.csv",
  "status": "queued",
  "columns": [
    "description",
    "material"
  ],
  "column_mapping": {
    "description": "description",
    "material": "material",
    "origin": "origin",
    "sku": "sku",
    "existing_code": "hts_code"
  },
  "market": "US",
  "dataset_version": "2026-SAMPLE",
  "validation": {
    "suggested_mapping": {
      "description": "description",
      "material": "material",
      "origin": "origin",
      "sku": "sku",
      "existing_code": "hts_code"
    },
    "precheck": {
      "total": 3,
      "empty": 0,
      "examples": 0,
      "invalid": 0,
      "duplicates": 0,
      "valid": 3,
      "warnings": 0,
      "issues": []
    },
    "final": {
      "total": 3,
      "empty": 0,
      "examples": 0,
      "invalid": 0,
      "duplicates": 0,
      "valid": 3,
      "warnings": 0,
      "issues": []
    },
    "lang": "en"
  },
  "total_rows": 3,
  "processed_rows": 0,
  "failed_rows": 0,
  "error": null,
  "save_to_catalog": false,
  "counts": {
    "pending": 3
  },
  "preview": []
}

GET /api/batches/{batch_id}/progress

The status, the counters and version, a token that changes whenever the batch or its rows changed. Poll this and read the rows again only when version differs from the one last seen. The token is opaque: compare it, do not parse it.

Path parameters

Name Type Description
batch_id string -

Returns 200 with BatchProgressOut.

Errors: 401 No valid API key was sent; 403 The role of the key, or the plan of the account, does not allow this call; 422 The request is not valid; 500 An unexpected failure.

Try it in the explorer

GET /api/batches/{batch_id}/progress
curl "https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544/progress" \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME"
import json
import os
import urllib.request

request = urllib.request.Request(
    "https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544/progress",
    headers={"X-API-Key": os.environ["HTS_PILOT_API_KEY"]},
    method="GET",
)
with urllib.request.urlopen(request) as response:
    print(json.load(response))
const response = await fetch("https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544/progress", {
  headers: { "X-API-Key": process.env.HTS_PILOT_API_KEY },
});
console.log(await response.json());
Response 200
{
  "id": "9058ee5650844af9b9d6f473bdf3c544",
  "status": "completed",
  "updated_at": "2026-10-03T16:07:52.103466",
  "total_rows": 3,
  "processed_rows": 3,
  "failed_rows": 0,
  "error": null,
  "counts": {
    "done": 3
  },
  "version": "f3bb25533d548f36"
}

Get a batch

GET /api/batches/{batch_id}

Path parameters

Name Type Description
batch_id string -

Query parameters

Name Type Required Description
preview boolean No Default false

Returns 200 with BatchOut.

Errors: 401 No valid API key was sent; 403 The role of the key, or the plan of the account, does not allow this call; 422 The request is not valid; 500 An unexpected failure.

Try it in the explorer

GET /api/batches/{batch_id}
curl "https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544" \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME"
import json
import os
import urllib.request

request = urllib.request.Request(
    "https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544",
    headers={"X-API-Key": os.environ["HTS_PILOT_API_KEY"]},
    method="GET",
)
with urllib.request.urlopen(request) as response:
    print(json.load(response))
const response = await fetch("https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544", {
  headers: { "X-API-Key": process.env.HTS_PILOT_API_KEY },
});
console.log(await response.json());
Response 200
{
  "id": "9058ee5650844af9b9d6f473bdf3c544",
  "created_at": "2026-10-03T16:07:51.820019",
  "updated_at": "2026-10-03T16:07:51.820019",
  "filename": "products.csv",
  "status": "uploaded",
  "columns": [
    "description",
    "material"
  ],
  "column_mapping": {
    "description": "description",
    "material": "material",
    "origin": "origin",
    "sku": "sku",
    "existing_code": "hts_code"
  },
  "market": "",
  "dataset_version": null,
  "validation": {
    "suggested_mapping": {
      "description": "description",
      "material": "material",
      "origin": "origin",
      "sku": "sku",
      "existing_code": "hts_code"
    },
    "precheck": {
      "total": 3,
      "empty": 0,
      "examples": 0,
      "invalid": 0,
      "duplicates": 0,
      "valid": 3,
      "warnings": 0,
      "issues": []
    }
  },
  "total_rows": 3,
  "processed_rows": 0,
  "failed_rows": 0,
  "error": null,
  "save_to_catalog": false,
  "counts": {
    "pending": 3
  },
  "preview": []
}

List batches

GET /api/batches

Query parameters

Name Type Required Description
limit integer No Minimum 1, maximum 100, default 20

Returns 200 with BatchOut[].

Errors: 401 No valid API key was sent; 403 The role of the key, or the plan of the account, does not allow this call; 422 The request is not valid; 500 An unexpected failure.

Try it in the explorer

GET /api/batches
curl "https://htspilot.com/api/batches" \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME"
import json
import os
import urllib.request

request = urllib.request.Request(
    "https://htspilot.com/api/batches",
    headers={"X-API-Key": os.environ["HTS_PILOT_API_KEY"]},
    method="GET",
)
with urllib.request.urlopen(request) as response:
    print(json.load(response))
const response = await fetch("https://htspilot.com/api/batches", {
  headers: { "X-API-Key": process.env.HTS_PILOT_API_KEY },
});
console.log(await response.json());
Response 200
[
  {
    "id": "9058ee5650844af9b9d6f473bdf3c544",
    "created_at": "2026-10-03T16:07:51.820019",
    "updated_at": "2026-10-03T16:07:52.103466",
    "filename": "products.csv",
    "status": "completed",
    "columns": [
      "description",
      "material"
    ],
    "column_mapping": {
      "description": "description",
      "material": "material",
      "origin": "origin",
      "sku": "sku",
      "existing_code": "hts_code"
    },
    "market": "US",
    "dataset_version": "2026-SAMPLE",
    "validation": {
      "suggested_mapping": {
        "description": "description",
        "material": "material",
        "origin": "origin",
        "sku": "sku",
        "existing_code": "hts_code"
      },
      "precheck": {
        "total": 3,
        "empty": 0,
        "examples": 0,
        "invalid": 0,
        "duplicates": 0,
        "valid": 3,
        "warnings": 0,
        "issues": []
      },
      "final": {
        "total": 3,
        "empty": 0,
        "examples": 0,
        "invalid": 0,
        "duplicates": 0,
        "valid": 3,
        "warnings": 0,
        "issues": []
      },
      "lang": "en"
    },
    "total_rows": 3,
    "processed_rows": 3,
    "failed_rows": 0,
    "error": null,
    "save_to_catalog": false,
    "counts": {
      "done": 3
    },
    "preview": []
  }
]

List the rows

GET /api/batches/{batch_id}/rows

Path parameters

Name Type Description
batch_id string -

Query parameters

Name Type Required Description
status string or null No -
offset integer No Minimum 0, default 0
limit integer No Minimum 1, maximum 2000, default 200

Returns 200 with BatchRowOut[].

Errors: 401 No valid API key was sent; 403 The role of the key, or the plan of the account, does not allow this call; 422 The request is not valid; 500 An unexpected failure.

Try it in the explorer

GET /api/batches/{batch_id}/rows
curl "https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544/rows" \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME"
import json
import os
import urllib.request

request = urllib.request.Request(
    "https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544/rows",
    headers={"X-API-Key": os.environ["HTS_PILOT_API_KEY"]},
    method="GET",
)
with urllib.request.urlopen(request) as response:
    print(json.load(response))
const response = await fetch("https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544/rows", {
  headers: { "X-API-Key": process.env.HTS_PILOT_API_KEY },
});
console.log(await response.json());
Response 200
[
  {
    "row_index": 2,
    "raw": {
      "description": "Men's T-shirt, knitted, 100% cotton, short sleeves",
      "material": "cotton",
      "origin": "VN",
      "sku": "EXAMPLE-TSH-001",
      "hts_code": "6109.10.00.12"
    },
    "status": "done",
    "issues": [],
    "duplicate_of": null,
    "lookup_id": "e60be79fad914ec88b759a060b258de0",
    "attempts": 1,
    "error": null,
    "result_status": "proposed",
    "recommended_code": "6109.10.00.14",
    "confidence": 0.75,
    "code_check": {
      "status": "valid",
      "code": "6109.10.00.12",
      "description": "Chapter 61: Articles of apparel and clothing accessories, knitted or crocheted > T-shirts, singlets, tank tops and similar garments, knitted or crocheted > Of cotton > Men's or boys' > T-shirts, all white, short hemmed sleeves, hemmed bottom, crew or round neckline, or V-neck, without pockets, trim or embroidery",
      "detail": "Valid declarable code",
      "comparison": "same_hs6"
    },
    "final_code": null
  },
  {
    "row_index": 3,
    "raw": {
      "description": "Cotton terry bath towel, 70 x 140 cm",
      "material": "cotton",
      "origin": "IN",
      "sku": "EXAMPLE-TWL-014",
      "hts_code": ""
    },
    "status": "done",
    "issues": [],
    "duplicate_of": null,
    "lookup_id": "f23fdb9bfa2e4c33930c1ac93418fd41",
    "attempts": 1,
    "error": null,
    "result_status": "proposed",
    "recommended_code": "6302.60.00.10",
    "confidence": 0.74,
    "code_check": {},
    "final_code": null
  }
]

Edit a row

PATCH /api/batches/{batch_id}/rows/{row_index}

Changes data in your account when executed. values maps column names of the file to their new text. row_index is the row number in the file (the first data row is 2).

Path parameters

Name Type Description
batch_id string -
row_index integer -

Request body (application/json)

Name Type Required Description
values object Yes -

Returns 200 with BatchOut.

Errors: 401 No valid API key was sent; 403 The role of the key, or the plan of the account, does not allow this call; 422 The request is not valid; 500 An unexpected failure.

Try it in the explorer

PATCH /api/batches/{batch_id}/rows/{row_index}
curl -X PATCH "https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544/rows/2" \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME" \
  -H "Content-Type: application/json" \
  -d '{
  "values": {
    "description": "Men'\''s T-shirt, knitted, 100% cotton, short sleeves"
  }
}'
import json
import os
import urllib.request

request = urllib.request.Request(
    "https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544/rows/2",
    data=json.dumps({
        "values": {"description": "Men's T-shirt, knitted, 100% cotton, short sleeves"},
    }).encode(),
    headers={"X-API-Key": os.environ["HTS_PILOT_API_KEY"], "Content-Type": "application/json"},
    method="PATCH",
)
with urllib.request.urlopen(request) as response:
    print(json.load(response))
const response = await fetch("https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544/rows/2", {
  method: "PATCH",
  headers: { "X-API-Key": process.env.HTS_PILOT_API_KEY, "Content-Type": "application/json" },
  body: JSON.stringify({
    "values": {
      "description": "Men's T-shirt, knitted, 100% cotton, short sleeves"
    }
  }),
});
console.log(await response.json());
Response 200
{
  "id": "9058ee5650844af9b9d6f473bdf3c544",
  "created_at": "2026-10-03T16:07:51.820019",
  "updated_at": "2026-10-03T16:07:52.058703Z",
  "filename": "products.csv",
  "status": "queued",
  "columns": [
    "description",
    "material"
  ],
  "column_mapping": {
    "description": "description",
    "material": "material",
    "origin": "origin",
    "sku": "sku",
    "existing_code": "hts_code"
  },
  "market": "US",
  "dataset_version": "2026-SAMPLE",
  "validation": {
    "suggested_mapping": {
      "description": "description",
      "material": "material",
      "origin": "origin",
      "sku": "sku",
      "existing_code": "hts_code"
    },
    "precheck": {
      "total": 3,
      "empty": 0,
      "examples": 0,
      "invalid": 0,
      "duplicates": 0,
      "valid": 3,
      "warnings": 0,
      "issues": []
    },
    "final": {
      "total": 3,
      "empty": 0,
      "examples": 0,
      "invalid": 0,
      "duplicates": 0,
      "valid": 3,
      "warnings": 0,
      "issues": []
    },
    "lang": "en"
  },
  "total_rows": 3,
  "processed_rows": 3,
  "failed_rows": 0,
  "error": null,
  "save_to_catalog": false,
  "counts": {
    "done": 2,
    "pending": 1
  },
  "preview": []
}

POST /api/batches/{batch_id}/retry

Changes data in your account when executed.

Path parameters

Name Type Description
batch_id string -

Returns 200 with BatchOut.

Errors: 401 No valid API key was sent; 403 The role of the key, or the plan of the account, does not allow this call; 422 The request is not valid; 500 An unexpected failure.

Try it in the explorer

POST /api/batches/{batch_id}/retry
curl -X POST "https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544/retry" \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME"
import json
import os
import urllib.request

request = urllib.request.Request(
    "https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544/retry",
    headers={"X-API-Key": os.environ["HTS_PILOT_API_KEY"]},
    method="POST",
)
with urllib.request.urlopen(request) as response:
    print(json.load(response))
const response = await fetch("https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544/retry", {
  method: "POST",
  headers: { "X-API-Key": process.env.HTS_PILOT_API_KEY },
});
console.log(await response.json());
Response 200
{
  "id": "9058ee5650844af9b9d6f473bdf3c544",
  "created_at": "2026-10-03T16:07:51.820019",
  "updated_at": "2026-10-03T16:07:52.103466",
  "filename": "products.csv",
  "status": "completed",
  "columns": [
    "description",
    "material"
  ],
  "column_mapping": {
    "description": "description",
    "material": "material",
    "origin": "origin",
    "sku": "sku",
    "existing_code": "hts_code"
  },
  "market": "US",
  "dataset_version": "2026-SAMPLE",
  "validation": {
    "suggested_mapping": {
      "description": "description",
      "material": "material",
      "origin": "origin",
      "sku": "sku",
      "existing_code": "hts_code"
    },
    "precheck": {
      "total": 3,
      "empty": 0,
      "examples": 0,
      "invalid": 0,
      "duplicates": 0,
      "valid": 3,
      "warnings": 0,
      "issues": []
    },
    "final": {
      "total": 3,
      "empty": 0,
      "examples": 0,
      "invalid": 0,
      "duplicates": 0,
      "valid": 3,
      "warnings": 0,
      "issues": []
    },
    "lang": "en",
    "retried_rows": 0
  },
  "total_rows": 3,
  "processed_rows": 3,
  "failed_rows": 0,
  "error": null,
  "save_to_catalog": false,
  "counts": {
    "done": 3
  },
  "preview": []
}

GET /api/batches/{batch_id}/export

Path parameters

Name Type Description
batch_id string -

Returns 200 with a file (application/vnd.openxmlformats-officedocument.spreadsheetml.sheet).

Errors: 401 No valid API key was sent; 403 The role of the key, or the plan of the account, does not allow this call; 422 The request is not valid; 500 An unexpected failure.

Try it in the explorer

The file is an Excel workbook in the language of the request (Languages).

GET /api/batches/{batch_id}/export
curl "https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544/export" \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME" \
  -o "products_hts_results.xlsx"
import json
import os
import urllib.request

request = urllib.request.Request(
    "https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544/export",
    headers={"X-API-Key": os.environ["HTS_PILOT_API_KEY"]},
    method="GET",
)
with urllib.request.urlopen(request) as response, open("products_hts_results.xlsx", "wb") as out:
    out.write(response.read())
import { writeFile } from "node:fs/promises";

const response = await fetch("https://htspilot.com/api/batches/9058ee5650844af9b9d6f473bdf3c544/export", {
  headers: { "X-API-Key": process.env.HTS_PILOT_API_KEY },
});
await writeFile("products_hts_results.xlsx", Buffer.from(await response.arrayBuffer()));
Response 200
{
  "file": true,
  "content_type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  "content_disposition": "attachment; filename=\"products_hts_results.xlsx\"",
  "bytes": 6847
}