Search HS Codes
curl --request GET \
--url https://htsapi.com/v1/hs \
--header 'Authorization: Bearer <token>'import requests
url = "https://htsapi.com/v1/hs"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://htsapi.com/v1/hs', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://htsapi.com/v1/hs",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://htsapi.com/v1/hs"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://htsapi.com/v1/hs")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://htsapi.com/v1/hs")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": [
{
"id": 123,
"description": "<string>",
"code": "<string>",
"normalized_code": "<string>",
"indent": 123,
"chapter": "<string>",
"heading": "<string>",
"subheading": "<string>",
"rates": {
"general": "<string>",
"special": "<string>",
"other": "<string>"
},
"units": [
"<string>"
],
"footnotes": [
{
"marker": "<string>",
"value": "<string>"
}
]
}
],
"meta": {
"total": 123,
"page": 123,
"limit": 123,
"total_pages": 123
},
"clarification": {
"needed": true,
"message": "<string>",
"suggestions": [
"<string>"
],
"grouped_by": "heading"
},
"ai_context": "<string>"
}{
"error": "<string>",
"message": "<string>",
"retry_after": 123
}{
"error": "<string>",
"message": "<string>",
"retry_after": 123
}{
"error": "<string>",
"message": "<string>",
"retry_after": 123
}API Reference
Get HS Codes
Search global HS codes (6-digit) by keyword, code prefix, or ingredient list
GET
/
hs
Search HS Codes
curl --request GET \
--url https://htsapi.com/v1/hs \
--header 'Authorization: Bearer <token>'import requests
url = "https://htsapi.com/v1/hs"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://htsapi.com/v1/hs', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://htsapi.com/v1/hs",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://htsapi.com/v1/hs"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://htsapi.com/v1/hs")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://htsapi.com/v1/hs")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": [
{
"id": 123,
"description": "<string>",
"code": "<string>",
"normalized_code": "<string>",
"indent": 123,
"chapter": "<string>",
"heading": "<string>",
"subheading": "<string>",
"rates": {
"general": "<string>",
"special": "<string>",
"other": "<string>"
},
"units": [
"<string>"
],
"footnotes": [
{
"marker": "<string>",
"value": "<string>"
}
]
}
],
"meta": {
"total": 123,
"page": 123,
"limit": 123,
"total_pages": 123
},
"clarification": {
"needed": true,
"message": "<string>",
"suggestions": [
"<string>"
],
"grouped_by": "heading"
},
"ai_context": "<string>"
}{
"error": "<string>",
"message": "<string>",
"retry_after": 123
}{
"error": "<string>",
"message": "<string>",
"retry_after": 123
}{
"error": "<string>",
"message": "<string>",
"retry_after": 123
}Search HS codes (6-digit international codes) using full-text search, code prefix matching, or ingredient-based search. Returns paginated results with optional clarification suggestions.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | No | Full-text search query (max 500 chars) |
code | string | No | Exact or prefix code match (e.g., ‘1101’ or ‘1101.00’) |
ingredients | string | No | Comma-separated list of ingredients (e.g., ‘wheat,flour’, max 500 chars) |
page | integer | No | Page number (default: 1, min: 1) |
limit | integer | No | Results per page (default: 25, min: 1, max: 100) |
Example Request
curl -X GET "https://htsapi.com/v1/hs?ingredients=wheat,flour&page=1&limit=25" \
-H "Authorization: Bearer your_hts_api_key"
Example Response
{
"data": [
{
"id": 1234,
"code": "1101.00",
"normalized_code": "110100",
"description": "Wheat or meslin flour",
"indent": 1,
"chapter": "11",
"heading": "1101",
"subheading": "110100",
"rates": {
"general": "Free",
"special": null,
"other": null
},
"units": [],
"footnotes": []
},
{
"id": 1235,
"code": "1001.99",
"normalized_code": "100199",
"description": "Wheat (other than durum), unmilled",
"indent": 1,
"chapter": "10",
"heading": "1001",
"subheading": "100199",
"rates": {
"general": "Free",
"special": null,
"other": null
},
"units": [],
"footnotes": []
}
],
"meta": {
"total": 15,
"page": 1,
"limit": 25,
"total_pages": 1
},
"clarification": {
"needed": true,
"message": "Your ingredient search for \"wheat,flour\" returned results across multiple processing levels. Please clarify:",
"suggestions": [
"Raw wheat grain (unmilled) → Chapter 10 (1001.xx) - Use when product is whole wheat kernels/grain",
"Wheat flour (plain, unmixed) → Chapter 11 (1101.00) - Use when plain wheat flour, no additives, not prepared food",
"Doughs/mixes → Chapter 19 (1901.20) - Use when flour is mixed with yeast, salt, sugar, oil, etc., but not yet baked",
"Finished baked goods → Chapter 19 (1905.xx) - Use when flour is no longer an ingredient but a finished food"
],
"grouped_by": "chapter"
}
}
Ingredient Search
Theingredients parameter allows you to search for codes by listing product ingredients. This is particularly useful for food products where the same ingredients can appear at different processing levels (raw, milled, prepared).
When ingredient searches span multiple processing levels, the API provides clarification suggestions to help you choose the correct classification.Authorizations
API key as Bearer token. Format: Bearer your_hts_api_key
Query Parameters
Full-text search query
Maximum string length:
500Exact or prefix code match (e.g., '1101' or '1101.00')
Maximum string length:
50Comma-separated list of ingredients (e.g., 'wheat,flour')
Maximum string length:
500Page number (default: 1)
Required range:
x >= 1Results per page (max: 100, default: 25)
Required range:
1 <= x <= 100