> ## Documentation index
> Fetch the complete documentation index at: https://docs.htspilot.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 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](/asynchronous-work.md)).
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](/lookups.md)) and can be charged ([Rate limits and quotas](/rate-limits.md#credits)). 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](/rate-limits.md)).

## 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` or `completed_with_errors` |
| `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 | Not set today: a failure belongs to a row, and a batch with failed rows ends as `completed_with_errors` |
| `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 |

## Download the template

`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.

**Example request**

```bash
curl "https://htspilot.com/api/batches/template" \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME" \
  -o "hts_lookup_template.xlsx"
```

**Example response** `200`

```json
{
  "file": true,
  "content_type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  "content_disposition": "attachment; filename=\"hts_lookup_template.xlsx\"",
  "bytes": 11735
}
```

Try it: https://docs.htspilot.com/explorer/#/Batches/getBatchTemplate

## 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.

**Example request**

```bash
curl -X POST "https://htspilot.com/api/batches" \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME" \
  -F "file=@products.csv"
```

**Example response** `200` (long lists and texts are cut)

```json
{
  "id": "6a84a87996544d39b99b76e83d59486c",
  "created_at": "2026-10-03T19:48:03.470967Z",
  "updated_at": "2026-10-03T19:48:03.474092Z",
  "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": ""
    }
  ]
}
```

Try it: https://docs.htspilot.com/explorer/#/Batches/uploadBatch

```bash
curl -X POST https://htspilot.com/api/batches \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME" \
  -F "file=@products.csv"
```

## 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.

**Example request**

```bash
curl -X POST "https://htspilot.com/api/batches/6a84a87996544d39b99b76e83d59486c/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
}'
```

**Example response** `200` (long lists and texts are cut)

```json
{
  "id": "6a84a87996544d39b99b76e83d59486c",
  "created_at": "2026-10-03T19:48:03.470967",
  "updated_at": "2026-10-03T19:48:03.474092",
  "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": ""
    }
  ]
}
```

Try it: https://docs.htspilot.com/explorer/#/Batches/validateBatch

## 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.

**Example request**

```bash
curl -X POST "https://htspilot.com/api/batches/6a84a87996544d39b99b76e83d59486c/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
}'
```

**Example response** `200` (long lists and texts are cut)

```json
{
  "id": "6a84a87996544d39b99b76e83d59486c",
  "created_at": "2026-10-03T19:48:03.470967",
  "updated_at": "2026-10-03T19:48:03.486727Z",
  "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": []
}
```

Try it: https://docs.htspilot.com/explorer/#/Batches/startBatch

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

## Follow the progress

`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.

**Example request**

```bash
curl "https://htspilot.com/api/batches/6a84a87996544d39b99b76e83d59486c/progress" \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME"
```

**Example response** `200`

```json
{
  "id": "6a84a87996544d39b99b76e83d59486c",
  "status": "completed",
  "updated_at": "2026-10-03T19:48:03.747413",
  "total_rows": 3,
  "processed_rows": 3,
  "failed_rows": 0,
  "error": null,
  "counts": {
    "done": 3
  },
  "version": "73af12f0adf70935"
}
```

Try it: https://docs.htspilot.com/explorer/#/Batches/getBatchProgress

## 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.

**Example request**

```bash
curl "https://htspilot.com/api/batches/6a84a87996544d39b99b76e83d59486c" \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME"
```

**Example response** `200` (long lists and texts are cut)

```json
{
  "id": "6a84a87996544d39b99b76e83d59486c",
  "created_at": "2026-10-03T19:48:03.470967",
  "updated_at": "2026-10-03T19:48:03.474092",
  "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": []
}
```

Try it: https://docs.htspilot.com/explorer/#/Batches/getBatch

## 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.

**Example request**

```bash
curl "https://htspilot.com/api/batches" \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME"
```

**Example response** `200` (long lists and texts are cut)

```json
[
  {
    "id": "6a84a87996544d39b99b76e83d59486c",
    "created_at": "2026-10-03T19:48:03.470967",
    "updated_at": "2026-10-03T19:48:03.747413",
    "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": []
  }
]
```

Try it: https://docs.htspilot.com/explorer/#/Batches/listBatches

## 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.

**Example request**

```bash
curl "https://htspilot.com/api/batches/6a84a87996544d39b99b76e83d59486c/rows" \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME"
```

**Example response** `200` (long lists and texts are cut)

```json
[
  {
    "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": "64449f0bcfd94c2dac722d0b40898386",
    "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": "78058903e9d24902b9793f55cb92284b",
    "attempts": 1,
    "error": null,
    "result_status": "proposed",
    "recommended_code": "6302.60.00.10",
    "confidence": 0.74,
    "code_check": {},
    "final_code": null
  }
]
```

Try it: https://docs.htspilot.com/explorer/#/Batches/listBatchRows

## 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.

**Example request**

```bash
curl -X PATCH "https://htspilot.com/api/batches/6a84a87996544d39b99b76e83d59486c/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"
  }
}'
```

**Example response** `200` (long lists and texts are cut)

```json
{
  "id": "6a84a87996544d39b99b76e83d59486c",
  "created_at": "2026-10-03T19:48:03.470967",
  "updated_at": "2026-10-03T19:48:03.702951Z",
  "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": []
}
```

Try it: https://docs.htspilot.com/explorer/#/Batches/editBatchRow

## Retry the failed rows

`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.

**Example request**

```bash
curl -X POST "https://htspilot.com/api/batches/6a84a87996544d39b99b76e83d59486c/retry" \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME"
```

**Example response** `200` (long lists and texts are cut)

```json
{
  "id": "6a84a87996544d39b99b76e83d59486c",
  "created_at": "2026-10-03T19:48:03.470967",
  "updated_at": "2026-10-03T19:48:03.747413",
  "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": []
}
```

Try it: https://docs.htspilot.com/explorer/#/Batches/retryBatch

## Download the results

`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.

**Example request**

```bash
curl "https://htspilot.com/api/batches/6a84a87996544d39b99b76e83d59486c/export" \
  -H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME" \
  -o "products_hts_results.xlsx"
```

**Example response** `200`

```json
{
  "file": true,
  "content_type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  "content_disposition": "attachment; filename=\"products_hts_results.xlsx\"",
  "bytes": 6843
}
```

Try it: https://docs.htspilot.com/explorer/#/Batches/exportBatch

The file is an Excel workbook in the language of the request ([Languages](/languages.md)).
