How to Automate Tariff Code Assignment Using an API (2026)
You can automate HTS tariff code assignment by sending product descriptions to a classification API that returns HTS codes (to 10 digits when the description supports it), duty figures, confidence levels, and CBP ruling citations as evidence. This replaces manual lookup in the USITC tariff schedule with a single POST request that typically takes 15-35 seconds.
Why Automate Tariff Code Assignment?
Manual HTS classification is the bottleneck in most import workflows. A trained customs broker spends 10-30 minutes per product looking up codes in the Harmonized Tariff Schedule, cross-referencing CBP rulings, and applying the WCO's General Rules of Interpretation. This process has three structural problems:
- Slow. Classifying a 500-SKU catalog takes weeks. New products wait for broker availability.
- Error-prone. Different brokers classify the same product differently. CBP penalty assessments for misclassification averaged $7,500 per entry in 2025.
- Expensive. Customs brokers charge $100-200 per classification. At scale, that's $50K-100K for a mid-size catalog.
An API call costs $0.05-0.10, typically returns in 15-35 seconds, and cites CBP ruling precedents as evidence. Results can vary somewhat between runs on the same input. It doesn't replace a broker for final filing decisions; it does the first pass of the research.
| Manual (broker) | API (htsapi.dev) | |
|---|---|---|
| Cost per classification | $100-200 | $0.05-0.10 |
| Time per classification | 10-30 minutes | Typically 15-35 seconds |
| Evidence provided | Varies by broker | CBP ruling citation + rationale |
| Consistency | Varies by broker | Cited rulings + GRI rationale on every call: repeatable evidence path |
| 500-product catalog | Days/weeks | About an hour (one call per product, 10 per minute per key; no batch endpoint) |
How the htsapi.dev Classification API Works
The API uses an agent-based approach. When you submit a product description, it:
- Searches 220K+ CBP rulings (our weekly-refreshed copy of the CROSS database database) for precedents matching your product
- Reads the HTS schedule from the USITC to identify candidate codes and legal notes
- Applies GRI rules (General Rules of Interpretation) to determine the correct classification
- Enriches with duty data from Census Bureau import statistics: duty actually collected on past imports
The response includes:
| Field | What it contains |
|---|---|
answer | The code at the depth your facts support; when short of 10 digits, the options and the question that decides them |
hts_code | Each candidate's 10-digit HTS code |
confidence | high, medium, or low |
rationale | Plain-English explanation of why this code applies |
rulings | CBP ruling numbers with links to the official CROSS database |
census_duties | What importers paid in the latest published month (Census, 10-digit line when there is enough trade, else 6-digit), last 3 months in recent_months, 12-month average in total_effective_rate_pct |
general_duty | Statutory MFN duty rate from the tariff schedule |
legal_notes | Section and chapter notes from the official schedule |
clarification | Follow-up question if the description is ambiguous (null otherwise) |
When the description is ambiguous, the API asks a clarification question instead of guessing. This is a deliberate design choice: a wrong classification with high confidence is worse than asking for more detail.
Step 1: Get Your API Key
Sign up at htsapi.dev and purchase a credit pack. Each successful /v1/classify call costs 1 credit. All other endpoints (HTS search, rulings search) are free with a key. The key is shown once after purchase (not emailed), so save it.
Set your key as an environment variable:
# Linux / macOS export HTS_API_KEY="your_api_key_here" # Windows PowerShell $env:HTS_API_KEY = "your_api_key_here"
Step 2: Send a Classification Request
Python
import os import requests resp = requests.post( "https://htsapi.dev/v1/classify", headers={"X-API-Key": os.environ["HTS_API_KEY"]}, json={ "description": "stainless steel insulated water bottle 500ml double wall vacuum", "material": "stainless steel", "country_of_origin": "China" } ) data = resp.json() print(data)
Node.js
const resp = await fetch("https://htsapi.dev/v1/classify", { method: "POST", headers: { "Content-Type": "application/json", "X-API-Key": process.env.HTS_API_KEY }, body: JSON.stringify({ description: "stainless steel insulated water bottle 500ml double wall vacuum", material: "stainless steel", country_of_origin: "China" }) }); const data = await resp.json(); console.log(data);
The request body accepts four fields:
| Field | Required | Notes |
|---|---|---|
description | Yes | 3-2000 characters. More detail produces better results. |
material | No | Primary material. HTS classification often hinges on this. |
category | No | Product category hint. |
country_of_origin | No | Gives Census duty figures for that country, which include Section 301/232 duties actually paid. |
Step 3: Parse the Response
A successful classification returns a JSON object with candidates ranked by confidence (abridged; duty figures illustrative):
{
"confident_to": "7323.93.00",
"candidates": [
{
"hts_code": "7323.93.00.50",
"description": "Table, kitchen or other household articles... of stainless steel",
"general_duty": "2%",
"census_duties": {
"country": "CHINA",
"period": "2025-06..2026-05",
"total_effective_rate_pct": 27.3,
"total_import_value_usd": 45200000,
"total_duty_collected_usd": 12339600,
"breakdown": [
{ "rp_code": "61", "rp_label": "Dutiable at the General (MFN) rate", "effective_rate_pct": 2.0 },
{ "rp_code": "69", "rp_label": "Dutiable under HTS chapter 99 (e.g. Section 301, 232), duty reported", "effective_rate_pct": 25.3 }
]
},
"confidence": "high",
"rationale": "Stainless steel insulated water bottles are classified under heading 7323 as household articles of stainless steel. The double-wall vacuum construction does not change the classification. CBP has consistently ruled similar products under 7323.93.00.",
"rulings": [
{
"ruling_number": "N284519",
"subject": "The tariff classification of a stainless steel water bottle from China",
"source_url": "https://rulings.cbp.gov/ruling/N284519"
}
],
"legal_notes": "--- SECTION XV ---\nNotes\n1. This section does not cover..."
}
],
"clarification": null
}
Key fields to use in your integration:
confident_to: The deepest level no answer to the open question could change (the same asanswer.code). If it's a full 10-digit code, the facts you gave settle the code; still review before filing. If it's only 4 digits, the description needs more detail.census_duties.total_effective_rate_pct: The 12-month average: duty collected divided by dutiable value on past imports of this 6-digit subheading from this country, including Section 301/232 duties actually paid. To price a shipment, readcensus_duties.recent_months: the latest 3 published months, at the 10-digit line when there is enough trade. From Census Bureau import data: a historical average, not the duty a specific shipment will owe.rulings: Direct links to CBP CROSS rulings you can cite as precedent.rationale: Plain-English explanation of the classification logic, useful for audit documentation.
Step 4: Handle Clarifications
When a product description is too vague, the API returns a clarification question instead of guessing. This prevents misclassification on ambiguous items.
Example: classifying "wall clock" without additional detail:
{
"confident_to": "9105",
"candidates": [
{
"hts_code": "9105.21.40.00",
"description": "Wall clocks, electrically operated",
"confidence": "medium"
},
{
"hts_code": "9105.11.40.00",
"description": "Wall clocks, mechanically operated",
"confidence": "medium"
}
],
"clarification": "Is the clock movement electric (battery/AC powered) or mechanical (spring/weight driven)?"
}
To resolve, resubmit with the additional detail:
# Resubmit with clarification detail resp = requests.post( "https://htsapi.dev/v1/classify", headers={"X-API-Key": os.environ["HTS_API_KEY"]}, json={ "description": "wall clock, battery-operated quartz movement, plastic case", "country_of_origin": "China" } )
With the added fact, the second call can go deeper, often to the full 10-digit code. In a user-facing application, display the clarification question to your user and append their answer to the description before resubmitting.
Integrating into Your Workflow
E-commerce: classify on product import
When a new product is added to your catalog or imported from a supplier feed, classify it automatically. Store the HTS code and duty figures alongside the product record.
ERP: batch classify a catalog
Loop over unclassified SKUs and classify each one. Store results in your ERP. Flag items where confident_to is shorter than 8 digits for manual review.
import os, time import requests API_KEY = os.environ["HTS_API_KEY"] products = [ {"sku": "WB-001", "desc": "stainless steel water bottle 500ml insulated", "origin": "China"}, {"sku": "TS-042", "desc": "men's 100% cotton knit t-shirt short sleeve", "origin": "Vietnam"}, {"sku": "CB-119", "desc": "lithium-ion battery pack 48V for electric bicycle", "origin": "China"}, ] for p in products: resp = requests.post( "https://htsapi.dev/v1/classify", headers={"X-API-Key": API_KEY}, json={"description": p["desc"], "country_of_origin": p["origin"]} ) result = resp.json() top = result["candidates"][0] needs_review = len(result["confident_to"] or "") < 10 print(f"{p['sku']}: {top['hts_code']} ({top['confidence']})" f{" ⚠ REVIEW" if needs_review else ""}) time.sleep(1) # respect rate limits
Customs broker: pre-screen before filing
Use the API as a first pass to classify shipments. Route high-confidence results to a quick review before entry preparation. Send medium- and low-confidence or clarification-needed items to a human broker.
Accuracy and Evidence
Accuracy claims require context. Here is what we measured: a 54-product test drawn from 2024+ CBP rulings, the source ruling hidden from the agent, 2 runs, 2026-10-01 (method):
| Metric | Value | What it means |
|---|---|---|
| 10-digit exact match | 69-76% | The API returned the exact 10-digit code that CBP assigned |
| 6-digit match | 83-89% | Correct at the international HS subheading level |
| 4-digit match | 85-91% | Correct heading |
| High-confidence answers | 35 of 40 exact | When the agent says "high", it was usually right at 10 digits |
Every result includes:
- CBP ruling citations when a relevant precedent exists in the 220K+ ruling database
- Census Bureau duty figures from actual import data: what was collected on past imports (a historical average), next to what the schedule says
- Legal notes from the official USITC tariff schedule
- Confidence level so you know when to trust the result and when to escalate
Pricing
| Pack | Credits | Price | Per classification |
|---|---|---|---|
| Starter | 100 | $10 | $0.10 |
| Standard | 1,000 | $50 | $0.05 |
What's free:
- Web UI classification at htsapi.dev: try the classifier before buying API credits
- HTS code search:
GET /v1/hts/search?q= - CBP rulings search:
GET /v1/rulings/search?q= - Balance check:
GET /v1/billing/balance
Only /v1/classify costs credits. Everything else is free with a key, within the rate limit of 10 requests per minute.
Frequently Asked Questions
How accurate is automated HTS classification?
On a 54-product test drawn from 2024+ CBP rulings (the source ruling hidden from the agent, 2 runs, 2026-10-01), the htsapi.dev classification API returned the exact 10-digit code 69-76% of the time, the right 6-digit subheading 83-89%, and the right 4-digit heading 85-91%. Every result includes a confidence level and CBP ruling citation when available, so you can verify the classification against official precedent before filing.
Can the API handle ambiguous product descriptions?
Yes. When a product description is too vague to classify confidently, the API returns a clarification question instead of guessing. For example, "wall clock" would prompt "Is the movement electric or mechanical?" You resubmit with the additional detail and receive a more precise classification.
What data sources does the API use?
The API searches over 220,000 CBP ruling precedents from the CROSS database, the official USITC Harmonized Tariff Schedule, Census Bureau import statistics for duty actually collected on past imports, and applies WCO General Rules of Interpretation (GRI) for classification logic. Rulings and the HTS schedule are refreshed weekly; Census figures cover the latest 12 months Census has published, about two months behind.
How fast is the API response?
Most classification requests take 15-35 seconds, sometimes up to about 60. An AI agent searches our copy of the CBP rulings and the HTS schedule, reads rulings and legal notes, then applies GRI reasoning. This is slower than a simple database lookup but produces evidence-backed results with citations. Rate limit is 10 requests per minute per API key.
Is there a free trial?
The web UI at htsapi.dev lets you classify products for free with no API key required. All non-classify endpoints (HTS search, rulings search) are free with an API key, within the rate limit. Paid API access for programmatic use starts at $10 for 100 credits.