Lookups
Classify one product and read the result - the lookup object, the recommended code, the other candidates, the reasons, the sources and what is still missing.
A lookup is one product description classified against one tariff schedule. It is created by
POST /api/classify, runs in the background (Asynchronous work) and ends with a
proposed code, a request for more information, or a request for review. A result is a suggestion for reference,
not a classification decision by a customs authority.
Lists, and POST /api/lookups/{lookup_id}/resolve, return the summary fields. Classify, get, rerun and the
decision return the summary fields and the detail fields.
Summary fields:
| Field | Type | Meaning |
|---|---|---|
id |
string | The id of the lookup |
created_at |
string | When it was created, ISO 8601, UTC |
kind |
string | single, batch for a row of a batch, or sku for a lookup made from the catalog |
batch_id, row_index |
string, integer, or null | The batch and the row it belongs to |
parent_lookup_id |
string or null | The lookup this one reruns |
description |
string | The product description that was sent |
market |
string | The import market: US, EU or VN (Tariff data) |
dataset_version |
string | The version of the tariff schedule it was classified against |
status |
string | queued, processing, proposed, needs_review, needs_info or error |
status_label |
string | The status, in the language of the reader |
recommended_code |
string or null | The proposed code, formatted as the schedule writes it |
recommended_description |
string or null | The official description of that line, with its parents |
hs6 |
string or null | The first six digits |
confidence |
number | From 0 to 1 |
review_flags |
array | Why a person should look: each entry has a code and a message in the language of the reader |
risk, risk_level |
integer, string | A score computed from the status, the confidence and the flags, and high, medium or low. sort=risk orders by it |
resolved |
boolean | Taken out of the review queue |
processing_ms |
integer | How long the classification took |
decision, decision_label |
string or null | The reviewer's decision: approved, overridden or rejected |
final_code, decided_at |
string or null | The code the decision settled on, and when |
created_by, created_by_name |
string or null | The account that created it |
sku_id |
integer or null | The SKU of the catalog it belongs to |
language |
string or null | The answer language (Languages) |
comment_count |
integer or null | Comments on the lookup |
Detail fields:
| Field | Type | Meaning |
|---|---|---|
input |
object | The fields that were sent: description, material, use, composition, origin, notes, market |
origin_label |
string or null | The country of origin, named in the language of the reader |
normalized |
object | The description as it was read: the cleaned text, its language, the category, materials and other attributes, and what is missing |
result |
object | The full answer, see below. Empty until the lookup is finished |
missing_info |
array | What the description leaves open, in the answer language |
error |
string or null | The message of a lookup that ended in error |
final_description, review_note, decided_by_name |
string or null | The reviewer's decision in words |
events |
array | The history: created, rerun, decisions, comments, each with who, when and a note |
progress |
object or null | The current stage while processing, otherwise null |
The parts of result an integration reads most:
| Field | Meaning |
|---|---|
recommended |
The proposed line: code, description, full_description, duty_rate, reasoning, citations, a duty estimate basis |
alternatives |
The other candidates, with the same fields as recommended, among them verdict and exclusion_reason |
summary, deciding_factors, uncertainties |
The reasoning in words, in the answer language |
questions |
Questions that would decide between candidates, with their options. Answer them with a rerun |
flags |
The same entries as review_flags |
sources |
What the answer cites: each with a key (as used in citations), url, title and snippet |
checks |
The automatic checks that ran on the answer, each ok or not |
legal |
The legal findings, in the answer language |
dataset |
The tariff schedule and version used |
disclaimer |
The statement that the result is a suggestion, in the language of the reader |
result has more fields than these (scores, timings, ranking detail); see the example answer.
POST /api/classify
Changes data in your account when executed. Creates a lookup with the status queued and classifies it in the background. Read GET /api/lookups/{lookup_id} until the status is no longer queued or processing. Spends credits.
Request body (application/json)
| Name | Type | Required | Description |
|---|---|---|---|
description |
string | Yes | Product description. Up to 2000 characters |
material |
string | No | Up to 500 characters |
use |
string | No | Up to 500 characters |
composition |
string | No | Up to 500 characters |
origin |
string | No | Up to 100 characters |
notes |
string | No | Other additional information. Up to 1000 characters |
market |
string | No | Import market: US, EU or VN. Up to 8 characters |
tariff_version |
string or null | No | Up to 64 characters |
sku_id |
integer or null | No | Link the result to a SKU in the catalog |
language |
string or null | No | Language the answer is written in: the reasons and explanations, the questions about missing information with their options, the legal findings and the warnings. A tag with a region is read by its primary subtag (en-US is en, ko-KR is ko), in any case. Without it: the language of the request (Accept-Language). Review flags, status labels and the other responses are not affected: they follow Accept-Language. Up to 35 characters |
Returns 202 with LookupDetail.
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.
Only description is required. origin takes a country code from GET /api/countries. Without market, the default market
of the service is used; without tariff_version, the active version of that market.
curl -X POST "https://htspilot.com/api/classify" \
-H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME" \
-H "Content-Type: application/json" \
-d '{
"description": "Men'\''s T-shirt, knitted, 100% cotton, short sleeves, crew neck",
"material": "cotton",
"use": "apparel",
"composition": "100% cotton",
"origin": "VN",
"notes": "",
"market": "US",
"language": "en"
}'import json
import os
import urllib.request
request = urllib.request.Request(
"https://htspilot.com/api/classify",
data=json.dumps({
"description": "Men's T-shirt, knitted, 100% cotton, short sleeves, crew neck",
"material": "cotton",
"use": "apparel",
"composition": "100% cotton",
"origin": "VN",
"notes": "",
"market": "US",
"language": "en",
}).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/classify", {
method: "POST",
headers: { "X-API-Key": process.env.HTS_PILOT_API_KEY, "Content-Type": "application/json" },
body: JSON.stringify({
"description": "Men's T-shirt, knitted, 100% cotton, short sleeves, crew neck",
"material": "cotton",
"use": "apparel",
"composition": "100% cotton",
"origin": "VN",
"notes": "",
"market": "US",
"language": "en"
}),
});
console.log(await response.json());202{
"id": "bcb6a35ae2694828b191f78ed704a9a9",
"created_at": "2026-10-03T16:07:51.322570",
"kind": "single",
"batch_id": null,
"row_index": null,
"parent_lookup_id": null,
"description": "Men's T-shirt, knitted, 100% cotton, short sleeves, crew neck",
"market": "US",
"dataset_version": "2026-SAMPLE",
"status": "queued",
"status_label": "New – queued",
"recommended_code": null,
"recommended_description": null,
"hs6": null,
"confidence": 0,
"review_flags": [],
"risk": 0,
"risk_level": "low",
"resolved": false,
"processing_ms": 0,
"decision": null,
"decision_label": null,
"final_code": null,
"decided_at": null,
"created_by": "d10db811d389470a8210b8210c023289",
"created_by_name": "Administrator",
"sku_id": null,
"language": "en",
"comment_count": 0,
"input": {
"description": "Men's T-shirt, knitted, 100% cotton, short sleeves, crew neck",
"material": "cotton",
"use": "apparel",
"composition": "100% cotton",
"origin": "VN",
"market": "US"
},
"origin_label": "Vietnam (VN)",
"normalized": {},
"result": {},
"missing_info": [],
"error": null,
"final_description": null,
"review_note": null,
"decided_by_name": null,
"events": [],
"progress": null
}
GET /api/lookups/{lookup_id}
Path parameters
| Name | Type | Description |
|---|---|---|
lookup_id |
string | - |
Returns 200 with LookupDetail.
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.
curl "https://htspilot.com/api/lookups/bcb6a35ae2694828b191f78ed704a9a9" \
-H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME"import json
import os
import urllib.request
request = urllib.request.Request(
"https://htspilot.com/api/lookups/bcb6a35ae2694828b191f78ed704a9a9",
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/lookups/bcb6a35ae2694828b191f78ed704a9a9", {
headers: { "X-API-Key": process.env.HTS_PILOT_API_KEY },
});
console.log(await response.json());200{
"id": "bcb6a35ae2694828b191f78ed704a9a9",
"created_at": "2026-10-03T16:07:51.322570",
"kind": "single",
"batch_id": null,
"row_index": null,
"parent_lookup_id": null,
"description": "Men's T-shirt, knitted, 100% cotton, short sleeves, crew neck",
"market": "US",
"dataset_version": "2026-SAMPLE",
"status": "proposed",
"status_label": "Proposed",
"recommended_code": "6109.10.00.14",
"recommended_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' > Other T-shirts",
"hs6": "610910",
"confidence": 0.75,
"review_flags": [
{
"code": "no_official_evidence",
"message": "No official source confirms the proposed code"
},
{
"code": "demo_data",
"message": "Tariff data is incomplete"
}
],
"risk": 18,
"risk_level": "low",
"resolved": true,
"processing_ms": 41,
"decision": null,
"decision_label": null,
"final_code": null,
"decided_at": null,
"created_by": "d10db811d389470a8210b8210c023289",
"created_by_name": "Administrator",
"sku_id": null,
"language": "en",
"comment_count": 0,
"input": {
"description": "Men's T-shirt, knitted, 100% cotton, short sleeves, crew neck",
"material": "cotton",
"use": "apparel",
"composition": "100% cotton",
"origin": "VN",
"market": "US"
},
"origin_label": "Vietnam (VN)",
"normalized": {
"raw_description": "Men's T-shirt, knitted, 100% cotton, short sleeves, crew neck",
"clean_description": "Men's T-shirt, knitted, 100% cotton, short sleeves, crew neck",
"search_text": "men's t-shirt, knitted, 100% cotton, short sleeves, crew neck cotton 100% cotton apparel t-shirts",
"language": "en",
"category": "apparel",
"materials": [
{
"name": "cotton",
"group": "textile",
"percent": 100
}
],
"construction": "knitted",
"gender": "men",
"state": null,
"electrical": false,
"extra": {
"material": "cotton",
"use": "apparel",
"composition": "100% cotton",
"origin": "VN"
},
"missing": [],
"flags": [],
"product_type": null,
"function": null,
"search_terms": [],
"extraction": {
"method": "rules"
},
"hs_headings": [],
"abbreviations": {},
"translation": null,
"material_groups": [
"textile"
]
},
"result": {
"status": "proposed",
"status_label": "Proposed",
"lang": "en",
"recommended": {
"code": "6109.10.00.14",
"code_digits": "6109100014",
"hs6": "610910",
"hs6_display": "6109.10",
"national_extension": "0014",
"description": "Other T-shirts",
"full_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' > Other T-shirts",
"duty_rate": "16.5%",
"retrieval_score": 0.9223,
"scores": {
"bm25": 11.6074,
"vector": 0.4017,
"rrf": 0.03226,
"overlap": 0.5,
"leaf_overlap": 1,
"attributes": 0.8,
"tree": 1,
"cross": 0,
"final": 0.9223,
"legal": 0
},
"verdict": "recommended",
"reasoning": "Tariff line: “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' > Other T-shirts”. Matches: heading usually used for 'apparel' products; matches main material: cotton; matches construction: knitted; matches intended user: men.",
"exclusion_reason": "",
"citations": [
"W1",
"N1"
],
"signals": [
"heading usually used for 'apparel' products",
"matches main material: cotton"
],
"legal": {
"status": "ok",
"penalty": 0,
"findings": []
},
"precedents": [],
"duty": {
"available": true,
"rate_text": "16.5%",
"rate_basis": "general",
"effective_pct": 16.5,
"max_pct": 16.5,
"additional_pct": 0,
"additional": [],
"may_apply": [],
"specific": false,
"currency": "USD"
}
},
"tentative": false,
"alternatives": [
{
"code": "6109.10.00.12",
"code_digits": "6109100012",
"hs6": "610910",
"hs6_display": "6109.10",
"national_extension": "0012",
"description": "T-shirts, all white, short hemmed sleeves, hemmed bottom, crew or round neckline, or V-neck, without pockets, trim or embroidery",
"full_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",
"duty_rate": "16.5%",
"retrieval_score": 0.8596,
"scores": {
"bm25": 22.6626,
"vector": 0.4315,
"rrf": 0.03279,
"overlap": 0.9,
"leaf_overlap": 0.357,
"attributes": 0.8,
"tree": 1,
"cross": 0,
"final": 0.8596,
"legal": 0
},
"verdict": "possible",
"reasoning": "Tariff line: “nglets, 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”. Matches: heading usually used for 'apparel' products; matches main material: cotton; matches construction: knitted; matches intended user: men.",
"exclusion_reason": "Same HS6 subheading, but the national line matches the details (user/style) less well than the top candidate.",
"citations": [
"W2",
"N1"
],
"signals": [
"heading usually used for 'apparel' products",
"matches main material: cotton"
],
"legal": {
"status": "ok",
"penalty": 0,
"findings": []
},
"precedents": [],
"duty": {
"available": true,
"rate_text": "16.5%",
"rate_basis": "general",
"effective_pct": 16.5,
"max_pct": 16.5,
"additional_pct": 0,
"additional": [],
"may_apply": [],
"specific": false,
"currency": "USD"
}
},
{
"code": "6110.20.20.20",
"code_digits": "6110202020",
"hs6": "611020",
"hs6_display": "6110.20",
"national_extension": "2020",
"description": "Men's or boys' sweatshirts of cotton",
"full_description": "Chapter 61: Articles of apparel and clothing accessories, knitted or crocheted > Sweaters, pullovers, sweatshirts, waistcoats (vests) and similar articles, knitted or crocheted > Of cotton > Men's or boys' sweatshirts of cotton",
"duty_rate": "",
"retrieval_score": 0.8095,
"scores": {
"bm25": 8.2297,
"vector": 0.3145,
"rrf": 0.02986,
"overlap": 0.4,
"leaf_overlap": 0.5,
"attributes": 0.88,
"tree": 0.9171,
"cross": 0,
"final": 0.8095,
"legal": 0
},
"verdict": "possible",
"reasoning": "Tariff line: “ 61: Articles of apparel and clothing accessories, knitted or crocheted > Sweaters, pullovers, sweatshirts, waistcoats (vests) and similar articles, knitted or crocheted > Of cotton > Men's or boys' sweatshirts of cotton”. Matches: heading usually used for 'apparel' products; matches main material: cotton; matches construction: knitted; matches intended user: men.",
"exclusion_reason": "Different HS subheading 611020; matches the description less well than the top candidate.",
"citations": [
"W3",
"N1"
],
"signals": [
"heading usually used for 'apparel' products",
"matches main material: cotton"
],
"legal": {
"status": "ok",
"penalty": 0,
"findings": []
},
"precedents": [],
"duty": {
"available": false,
"rate_text": ""
}
}
],
"confidence": 0.75,
"flags": [
{
"code": "no_official_evidence",
"message": "No official source confirms the proposed code"
},
{
"code": "demo_data",
"message": "Tariff data is incomplete"
}
],
"uncertainties": [],
"missing_info": [],
"questions": [],
"summary": "Proposed 6109.10.00.14 based on how well the description and attributes match.",
"deciding_factors": [
"6109.10.00.14: heading usually used for 'apparel' products",
"6109.10.00.14: matches main material: cotton"
],
"duty": {
"origin": "VN",
"country": "VN",
"codes_compared": 2,
"min_pct": 16.5,
"max_pct": 16.5,
"spread_pp": 0
},
"raw_confidence": 0.75,
"sources": [
{
"key": "W1",
"url": "https://hts.usitc.gov/",
"title": "Loaded tariff data – US 2026-SAMPLE – 6109.10.00.14",
"publisher": "Mô phỏng theo cấu trúc bản xuất JSON của USITC (hts.usitc.gov). Dòng thuế 8–10 số và mô tả được rút gọn/minh họa.",
"snippet": "6109.10.00.14: 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' > Other T-shirts",
"accessed_at": "2026-10-03T16:07:51.362411+00:00",
"is_official": false,
"is_demo": true,
"provider": "tariff_data",
"related_codes": [
"6109100014"
]
},
{
"key": "W2",
"url": "https://hts.usitc.gov/",
"title": "Loaded tariff data – US 2026-SAMPLE – 6109.10.00.12",
"publisher": "Mô phỏng theo cấu trúc bản xuất JSON của USITC (hts.usitc.gov). Dòng thuế 8–10 số và mô tả được rút gọn/minh họa.",
"snippet": "6109.10.00.12: 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",
"accessed_at": "2026-10-03T16:07:51.362411+00:00",
"is_official": false,
"is_demo": true,
"provider": "tariff_data",
"related_codes": [
"6109100012"
]
}
],
"precedents": [],
"legal": {
"guidance": [
{
"rule": "gri6-same-level",
"effect": "guidance",
"ref": "GRI 6",
"note_ref": "GRI6",
"params": {
"dominant": "cotton",
"percent": "100"
},
"message": "Subheadings are compared only with subheadings at the same level, by their terms and the related notes."
}
],
"excluded": [
{
"code": "6205202046",
"code_display": "6205.20.20.46",
"findings": [
{
"rule": "ch62-not-knitted",
"effect": "exclude",
"ref": "HS Chapter 62, Note 1",
"note_ref": "62",
"params": {
"dominant": "cotton",
"percent": "100"
},
"message": "Chapter 62 excludes knitted or crocheted articles (other than those of heading 62.12); the product is knitted."
}
]
},
{
"code": "6205202016",
"code_display": "6205.20.20.16",
"findings": [
{
"rule": "ch62-not-knitted",
"effect": "exclude",
"ref": "HS Chapter 62, Note 1",
"note_ref": "62",
"params": {
"dominant": "cotton",
"percent": "100"
},
"message": "Chapter 62 excludes knitted or crocheted articles (other than those of heading 62.12); the product is knitted."
}
]
}
],
"rules_fired": [
"gender_line",
"ch62-not-knitted"
]
},
"pipeline": {
"understanding": {
"method": "rules"
},
"translation": null,
"sufficient_info": true,
"early_exit": false,
"tree": {
"chapters": [
{
"code": "61",
"title": "Articles of apparel and clothing accessories, knitted or crocheted",
"score": 1.15
},
{
"code": "62",
"title": "Articles of apparel and clothing accessories, not knitted or crocheted",
"score": 1.087
}
],
"headings": [
{
"code": "6109",
"title": "T-shirts, singlets, tank tops and similar garments, knitted or crocheted",
"score": 1.15
},
{
"code": "6205",
"title": "Men's or boys' shirts (not knitted or crocheted)",
"score": 1.087
}
],
"hs6": 26,
"leaves": 43,
"widened": false
},
"retrievers": {
"bm25": 24,
"vector": 40,
"cross": 0,
"precedents": 0
},
"reranker": "default",
"calibrated": false,
"pool": 32,
"legal_excluded": 5,
"shortlist": null,
"top_k": 16,
"top_k_codes": [
"6109100014",
"6109100012"
],
"line_select": null,
"national_line": null
},
"ranking": {
"model": "default",
"candidates": [
{
"code": "6109100014",
"hs6": "610910",
"features": {
"rrf": 0.9839,
"bm25": 0.5122,
"vector": 0.4017,
"overlap": 0.5,
"leaf_overlap": 1,
"attributes": 0.8,
"tree": 1,
"cross": 0,
"legal": 0,
"xrerank": 0
}
},
{
"code": "6109100012",
"hs6": "610910",
"features": {
"rrf": 1,
"bm25": 1,
"vector": 0.4315,
"overlap": 0.9,
"leaf_overlap": 0.3571,
"attributes": 0.8,
"tree": 1,
"cross": 0,
"legal": 0,
"xrerank": 0
}
}
]
},
"notes": [
{
"key": "N1",
"doc_type": "chapter_note",
"ref_code": "61",
"title": "Chapter 61 – Scope",
"content": "Chapter 61 applies only to made up knitted or crocheted articles. Heading 6109 covers T-shirts, singlets and tank tops. Articles of apparel that are not knitted or crocheted fall in Chapter 62. [Illustrative summary for demo mode – check against the official text before use.]",
"source_url": "https://hts.usitc.gov/"
},
{
"key": "N2",
"doc_type": "gri",
"ref_code": "GRI1",
"title": "GRI 1 – Terms of headings and legal notes",
"content": "Classification is determined according to the terms of the headings and any relative Section or Chapter Notes; titles of sections and chapters are for ease of reference only. [Illustrative summary for demo mode – check against the official text before use.]",
"source_url": "https://hts.usitc.gov/"
}
],
"checks": [
{
"check": "evidence_matches_source",
"ok": true,
"detail": "W1",
"label": "Evidence matches source"
},
{
"check": "evidence_matches_source",
"ok": true,
"detail": "W2",
"label": "Evidence matches source"
}
],
"warnings": [],
"timings_ms": {
"understand": 11,
"retrieve": 16,
"legal": 3,
"evidence": 0,
"llm": 0,
"validate": 3,
"duty": 1
},
"dataset": {
"id": "00641a7ade5b4bf6afe5db0a0d2ee585",
"market": "US",
"version": "2026-SAMPLE",
"name": "HTSUS – bộ dữ liệu mẫu (DEMO, không phải dữ liệu chính thức)",
"is_demo": true,
"source_name": "Mô phỏng theo cấu trúc bản xuất JSON của USITC (hts.usitc.gov). Dòng thuế 8–10 số và mô tả được rút gọn/minh họa.",
"source_url": "https://hts.usitc.gov/",
"loaded_at": "2026-10-03T16:07:51.131282",
"national_digits": 10,
"effective_date": "2026-01-01"
},
"disclaimer": "This result is an automated suggestion for reference only, not an official classification decision. The declarant is responsible for the declared code; for complex cases, request an advance ruling from the customs authority."
},
"missing_info": [],
"error": null,
"final_description": null,
"review_note": null,
"decided_by_name": null,
"events": [
{
"id": 1,
"action": "created",
"user_name": "Administrator",
"user_role": "admin",
"from_code": null,
"to_code": "6109.10.00.14",
"note": "AI: Proposed",
"dataset_version": "2026-SAMPLE",
"created_at": "2026-10-03T16:07:51.371470"
},
{
"id": 2,
"action": "rerun",
"user_name": "Administrator (API: Documentation examples)",
"user_role": "admin",
"from_code": null,
"to_code": null,
"note": "Rerun with additional details → 654260f79ab647b699d7f69796bb7da4",
"dataset_version": "2026-SAMPLE",
"created_at": "2026-10-03T16:07:51.562452"
}
],
"progress": null
}
GET /api/lookups
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
q |
string or null | No | Up to 200 characters |
status |
string[] or null | No | - |
market |
string or null | No | - |
kind |
string or null | No | - |
decision |
string or null | No | - |
page |
integer | No | Minimum 1, default 1 |
page_size |
integer | No | Minimum 1, maximum 200, default 20 |
sort |
one of: newest, oldest, confidence, risk | No | Newest (default), oldest, confidence (least certain first), or risk (highest first, then oldest first). With confidence, queued, processing and failed lookups (confidence 0.0) come first. Default "newest" |
date_from |
string or null | No | Created on or after this day (UTC) |
date_to |
string or null | No | Created on or before this day (UTC) |
created_by |
string or null | No | User id, or 'me'. Up to 32 characters |
confidence_min |
number or null | No | Minimum 0, maximum 1 |
confidence_max |
number or null | No | Minimum 0, maximum 1 |
flag |
string or null | No | Review flag code, e.g. low_confidence. Pattern ^[a-z0-9_]{1,40}$ |
Returns 200 with Page.
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.
A key with the entry role lists the lookups of its own account. status may be repeated to ask for several
states. See Pagination.
curl "https://htspilot.com/api/lookups?page=1&page_size=20" \
-H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME"import json
import os
import urllib.request
request = urllib.request.Request(
"https://htspilot.com/api/lookups?page=1&page_size=20",
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/lookups?page=1&page_size=20", {
headers: { "X-API-Key": process.env.HTS_PILOT_API_KEY },
});
console.log(await response.json());200{
"items": [
{
"id": "bcb6a35ae2694828b191f78ed704a9a9",
"created_at": "2026-10-03T16:07:51.322570",
"kind": "single",
"batch_id": null,
"row_index": null,
"parent_lookup_id": null,
"description": "Men's T-shirt, knitted, 100% cotton, short sleeves, crew neck",
"market": "US",
"dataset_version": "2026-SAMPLE",
"status": "proposed",
"status_label": "Proposed",
"recommended_code": "6109.10.00.14",
"recommended_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' > Other T-shirts",
"hs6": "610910",
"confidence": 0.75,
"review_flags": [
{
"code": "no_official_evidence",
"message": "No official source confirms the proposed code"
},
{
"code": "demo_data",
"message": "Tariff data is incomplete"
}
],
"risk": 18,
"risk_level": "low",
"resolved": false,
"processing_ms": 41,
"decision": null,
"decision_label": null,
"final_code": null,
"decided_at": null,
"created_by": "d10db811d389470a8210b8210c023289",
"created_by_name": "Administrator",
"sku_id": null,
"language": "en",
"comment_count": 0
}
],
"total": 1,
"page": 1,
"page_size": 20
}
POST /api/lookups/{lookup_id}/rerun
Changes data in your account when executed. Runs the lookup again with the fields you send added to, or replacing, the ones it had. The answer is a new lookup; the old one is marked resolved. It is written in the language of the lookup it continues, unless the request names another language. Spends credits.
Path parameters
| Name | Type | Description |
|---|---|---|
lookup_id |
string | - |
Request body (application/json)
| Name | Type | Required | Description |
|---|---|---|---|
description |
string or null | No | Up to 2000 characters |
material |
string or null | No | Up to 500 characters |
use |
string or null | No | Up to 500 characters |
composition |
string or null | No | Up to 500 characters |
origin |
string or null | No | Up to 100 characters |
notes |
string or null | No | Up to 1000 characters |
market |
string or null | No | Up to 8 characters |
tariff_version |
string or null | No | Up to 64 characters |
language |
string or null | No | Language the answer is written in: the reasons and explanations, the questions about missing information with their options, the legal findings and the warnings. A tag with a region is read by its primary subtag (en-US is en, ko-KR is ko), in any case. Without it: the language of the lookup that is run again. Review flags, status labels and the other responses are not affected: they follow Accept-Language. Up to 35 characters |
Returns 202 with LookupDetail.
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.
Send only the fields that change. The answer is a new lookup with parent_lookup_id set; the old one is marked
resolved. This is how a needs_info lookup is continued: add what missing_info and result.questions ask
for.
curl -X POST "https://htspilot.com/api/lookups/bcb6a35ae2694828b191f78ed704a9a9/rerun" \
-H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME" \
-H "Content-Type: application/json" \
-d '{
"composition": "60% cotton, 40% polyester",
"notes": "Crew neck, no pockets"
}'import json
import os
import urllib.request
request = urllib.request.Request(
"https://htspilot.com/api/lookups/bcb6a35ae2694828b191f78ed704a9a9/rerun",
data=json.dumps({"composition": "60% cotton, 40% polyester", "notes": "Crew neck, no pockets"}).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/lookups/bcb6a35ae2694828b191f78ed704a9a9/rerun", {
method: "POST",
headers: { "X-API-Key": process.env.HTS_PILOT_API_KEY, "Content-Type": "application/json" },
body: JSON.stringify({
"composition": "60% cotton, 40% polyester",
"notes": "Crew neck, no pockets"
}),
});
console.log(await response.json());202{
"id": "654260f79ab647b699d7f69796bb7da4",
"created_at": "2026-10-03T16:07:51.562452",
"kind": "single",
"batch_id": null,
"row_index": null,
"parent_lookup_id": "bcb6a35ae2694828b191f78ed704a9a9",
"description": "Men's T-shirt, knitted, 100% cotton, short sleeves, crew neck",
"market": "US",
"dataset_version": "2026-SAMPLE",
"status": "queued",
"status_label": "New – queued",
"recommended_code": null,
"recommended_description": null,
"hs6": null,
"confidence": 0,
"review_flags": [],
"risk": 0,
"risk_level": "low",
"resolved": false,
"processing_ms": 0,
"decision": null,
"decision_label": null,
"final_code": null,
"decided_at": null,
"created_by": "d10db811d389470a8210b8210c023289",
"created_by_name": "Administrator",
"sku_id": null,
"language": "en",
"comment_count": 0,
"input": {
"description": "Men's T-shirt, knitted, 100% cotton, short sleeves, crew neck",
"material": "cotton",
"use": "apparel",
"composition": "60% cotton, 40% polyester",
"origin": "VN",
"notes": "Crew neck, no pockets",
"market": "US",
"tariff_version": "2026-SAMPLE"
},
"origin_label": "Vietnam (VN)",
"normalized": {},
"result": {},
"missing_info": [],
"error": null,
"final_description": null,
"review_note": null,
"decided_by_name": null,
"events": [],
"progress": null
}
GET /api/stats
Returns 200 with a JSON object, as in the example.
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.
curl "https://htspilot.com/api/stats" \
-H "X-API-Key: hts_EXAMPLE_KEY_REPLACE_ME"import json
import os
import urllib.request
request = urllib.request.Request(
"https://htspilot.com/api/stats",
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/stats", {
headers: { "X-API-Key": process.env.HTS_PILOT_API_KEY },
});
console.log(await response.json());200{
"by_status": {
"proposed": 1
},
"total": 1,
"pending_review": 0,
"open_alerts": 0
}