HS Code & Tariff API

Duty straight off the official schedule, with the revision attached

The HS Code & Tariff API returns HS/HTS commodity classification and duty data as clean JSON.

no credit card1,000 free credits · instant API key · live in 10 seconds
Missing a HS Code & Tariff endpoint, or need a source we don't have yet?Contact us real people · same-day reply.
H
/hs-code/v1

8 active endpoints, on 1, 2, 3, 4 and 8 credit tiers.

  • POST/hs-code/v1/hs_lookup
  • POST/hs-code/v1/classify
  • POST/hs-code/v1/landed_cost
  • POST/hs-code/v1/schedules_status
  • POST/hs-code/v1/batch_classify
  • POST/hs-code/v1/browse
  • POST/hs-code/v1/validate
  • +1 more

What HS Code & Tariff endpoints does ReefAPI ship?

8 live read endpoints. Read-only data API: no writes, no account actions, no dashboard access on the target site.

8 endpoints

hs_lookup

1 cr

One HS/HTS/commodity code + destination (US|UK) → the official tariff line.

required
code, destination
optional

classify

4 cr

Product description (+materials) + destination → ranked candidate HS codes with a confidence…

required
description, destination
optional
materials, limit, min_confidence

landed_cost

8 cr

HS code (or description → auto-classified) + destination + value (+origin, currency, shipping…

required
destination, value
optional
code, description, origin, currency, shipping, materials

schedules_status

1 cr

Freshness + coverage of the underlying official schedules (US HTS revision, UK tariff reachab…

required
optional

batch_classify

3 cr

Up to 25 products in one call (discounted).

required
items, destination
optional
limit, min_confidence

browse

1 cr

Navigate the tariff tree without knowing a keyword.

required
destination
optional
node

validate

1 cr

Check whether a code is a real, current tariff code in the chosen market.

required
code, destination
optional

cross_country

2 cr

One 6-digit HS subheading (the WCO-international level shared by every member country) → the…

required
hs6
optional

Every parameter, every allowed value →

HS Code & Tariff API

3 of 8 endpoints, ready to run

View docs ↗

One code, one market, the official tariff line: the description, the units, the third-country duty rate with the percentage parsed out, the special and preference programmes with their country codes, the column-two rate, any footnotes — and dozens of rows of surrounding tariff context so you can see the lines either side of yours.

1 credit2 required · 0 optional
POST/hs-code/v1/hs_lookup
ok1555 ms · 1 records · sample
{
  "ok": true,
  "meta": {
    "api": "hs-code",
    "endpoint": "hs_lookup",
    "mode": "live",
    "latency_ms": 1555.2,
    "record_count": 1,
    "cache_hit": false
  },
  "data": {
    "destination": "US",
    "code": "6109.10.00",
    "query_code": "6109.10",
    "record": {
      "hts_code": "6109.10.00",
      "hts_code_digits": "61091000",
      "indent": 1,
      "description": "Of cotton",
      "is_superior": false,
      "units": [],
      "duty": {
        "general_mfn": "16.5%",
        "general_mfn_pct": 16.5,
        "special": "Free (AU,BH,CL,CO,IL,JO,KR,MA,OM,P,PA,PE,S,SG)",
        "column_2": "90%",
        "rate_note": null,
        "additional_duties": null,
        "quota_quantity": null
      },
      "footnotes": []
    },
    "context": [
      {
        "hts_code": "6109",
        "description": "T-shirts, singlets, tank tops and similar garments, knitted or crocheted:",
        "general_mfn": null
      },
      {
        "hts_code": "6109.10.00",
        "description": "Of cotton",
        "general_mfn": "16.5%"
      },
      {
        "hts_code": "6109.10.00.04",
        "description": "T-shirts, all white, short hemmed sleeves, hemmed bottom, crew or round neckline, or V-neck with a mitered seam at the center of the V, without pockets, trim or embroidery (352)",
        "general_mfn": null
      }
    ],
    "schedule_version": "2026HTSRev17",
    "source": "USITC HTS (hts.usitc.gov)",
    "disclaimer": "Reference classification and rates from the official US (USITC HTS) and UK (HMRC Trade Tariff) schedules — informational only, NOT binding customs or legal advice. Landed-cost figures are estimates. Anti-dumping/countervailing duties, Section 301/232 additional tariffs, rules-of-origin, trade-preference eligibility, quotas and special programs are not fully modelled. Verify the final HS code and duty with a licensed customs broker before relying on it."
  }
}
Real response, fetched from the live endpoint with the parameters on the left — trimmed to the first few rows, with seller names left out. Press Try it for the untrimmed response.

How the HS Code & Tariff API works

HS Code & Tariff is a normal ReefAPI surface — the same four rules that hold for every other engine on the key.

01
Authenticate
x-api-key header

No OAuth app, no request signing, no per-site account. One key covers all 184 engines.

02
Call
POST /hs-code/v1/…

Every route is a POST with a JSON body. Parameters are validated against the published schema before anything is charged.

03
Pay
1 or 2 or 3 or 4 or 8 credits per call

Credits, not seats. Failed and blocked calls are never charged, and cache hits cost nothing.

04
Read
{ ok, data, meta, error }

One envelope everywhere. meta carries latency_ms, record_count and the endpoint that answered.

Price a shipment you have not classified yet

There are two very different steps here and conflating them is how importers get surprised at the border: FINDING a code is a judgement call, and LOOKING UP its duty is a fact. This engine does both and is explicit about which is which.

01classify
POST/hs-code/v1/classify
{"description": "<what you are importing>", "destination": "US"}

A ranked shortlist with a confidence band and a review flag. Treat it as candidates for a broker to confirm, never as an answer — the measurement below says why.

02hs_lookup
POST/hs-code/v1/hs_lookup
{"code": "<the code your broker confirmed>", "destination": "US"}

The exact official line: duty rate, preference programmes, footnotes, and the schedule revision the rate was read from.

03landed_cost
POST/hs-code/v1/landed_cost
{"destination": "US", "code": "<same code>", "value": 12000, "origin": "CN", "shipping": 800}

Duty, tax and total, with an assumptions list naming every additional tariff programme that was not applied.

A landed-cost figure you can put in front of a finance team with the schedule version, the origin assumption and the excluded tariff programmes attached — rather than a number whose provenance nobody can reconstruct.

request
curl -X POST https://api.reefapi.com/hs-code/v1/hs_lookup \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"code":"8471.30.0100","destination":"US"}'
response envelope
{
  "ok": true,
  "data": { … },
  "meta": {
    "api": "hs-code",
    "endpoint": "hs_lookup",
    "mode": "live",
    "latency_ms": …,
    "record_count": …
  },
  "error": null
}

Why a code returns no duty rate: declarable versus not

This is the single thing that confuses people, and it is not about how many digits your code has. A tariff line only carries rates if it is declarable — the level you could actually put on a customs entry. Everything above that is a classification bucket and correctly returns null rates plus its children. All rows measured against the UK schedule.

CodedeclarableWhat comes back
6403 (4-digit heading)falsedescription, an explanatory note, and context[] listing 60 child lines. import_duty and vat are both null — there is no rate at this level to return.
6403120000 (ski boots)truethird-country MFN 8.0%, a VAT rate, preference_measures 56, the full section XII / chapter 64 / heading 6403 hierarchy, validity_start 1996-01-01, validity_end null, and a BTI link
6109100000 (T-shirts)falseten digits and still no rates — digit count does not decide declarability
8471300000 (portable computers)trueduty 0.0%, VAT 20.0%
destination: UKHMRC Online Trade Tariff, live. Codes are UK commodity codes.
destination: USUSITC Harmonized Tariff Schedule. HTS lines are a different national code space — a UK commodity code is not an HTS line below 6 digits.
destination: anything elseout of scope in v1. The EU is not covered and we say so rather than returning an approximation.

Every response carries schedule_version and a disclaimer. These are the official published schedules, but a code is only legally binding when a customs authority says so — the bti_url on each declarable line is the route to a binding decision. Treat everything here as reference, not advice.

Two official schedules, one honest weakness

Measured against the live gateway on both markets and on six plain-English product descriptions. The second row is the most important thing on this page.

Two markets, named, versioned and dated

The United States from the USITC Harmonized Tariff Schedule and the United Kingdom from the HMRC trade tariff. Every response carries the schedule revision it read, the source it came from and a licence note. A separate status call reports both markets as live with their versions and refresh behaviour, and reports the EU as explicitly out of scope rather than silently absent.

Against us: `classify` is a keyword shortlist, and we measured how far off

How you word the description decides almost everything. Bare two-word inputs got the first row right once in five: 'laptop computer' ranked a hand-operated input device, 'leather handbag' ranked belts-and-bandoliers, 'stainless steel screws' ranked seamless stainless pipe. Adding the words a tariff schedule itself uses lifted it to six of twelve, and the correct heading was somewhere in the ten candidates on ten of twelve. So read the list, not the first row, and describe the goods the way a customs schedule would. The review-required flag catches most of the misses but not all: 'stainless steel screws' came back banded high with review_required false, and it was wrong. The engine's own note calls the score a relevance heuristic rather than a classification — believe it, and never let classify write a code into a customs entry unchecked.

Where the code is exact, the duty is exact

That weakness is confined to the guessing step. Given a code, the lookup returns the schedule's own line: the third-country rate as published, the parsed percentage, the free-rate programme list with its country codes, the column-two rate, and the surrounding tariff tree so you can check you are on the right branch. This is a read of a government file, not an inference.

landed_cost tells you what it did NOT include

A US estimate on Chinese-origin goods returned an assumptions list saying, in plain words, that the general third-country rate was applied and that additional-tariff programmes, anti-dumping and countervailing duties and preference rates were not. For an importer from China that gap is often larger than the duty itself, and it is stated in the response rather than buried in a footer.

The tax line is explained rather than zeroed

A US estimate returns a note saying there is no federal import VAT and that state sales tax and the merchandise and harbour processing fees are not included, instead of a bare zero you would have to interpret. The UK route taxes the CIF value, so shipping enters the tax base — and the assumptions say that too.

No currency conversion, ever, and it says so

Everything comes back in the currency you passed in, and the assumptions list states that no conversion was performed. An engine that quietly converted at an unstated rate would be a worse product than one that refuses to, because the error would be invisible.

validate separates a typo from a retired code

A well-formed but unknown code comes back invalid with a reason distinguishing a typo, an expired or superseded line and a non-declarable stub, plus the nearest valid parent to walk down from. That is the check to run over an existing product catalogue before a schedule revision breaks it.

It says out loud that it is not customs advice

Every response carries a disclaimer naming what is not modelled — additional tariff programmes, anti-dumping, rules of origin, preference eligibility, quotas — and saying to confirm with a licensed broker. People make money decisions with this data, so the page says the same thing the payload does rather than selling past it.

What people build with HS Code & Tariff

The jobs this data is most often used for.

8

endpoints

1/2/3/4/8

credits per call

01

Cross-border e-commerce tools call classify then landed_cost to quote duties and taxes at checkout.

02

Trade-compliance teams use hs_lookup and validate to confirm the correct code and duty rate.

03

Logistics products use cross_country to compare tariffs for a commodity across destinations.

What HS Code & Tariff data costs

The cheapest call here is 1 credit, so $15/mo (Pro) buys 10,000 of them — $1.50 per 1,000 credits. Credits roll over and never expire, and failed or blocked calls are not charged.

Full pricing →
$0.67–$1.50 / 1,000 credits
  • 1,000 free credits on signup, no card
  • One key, all 184 APIs, one credit pool
  • Failed and blocked calls are never charged
  • Credits roll over and never expire

Call it in two lines

Sign up, get 1,000 credits and one key that works on every engine. Then this is the whole protocol.

curl
curl -X POST https://api.reefapi.com/hs-code/v1/hs_lookup \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"code":"8471.30.0100","destination":"US"}'
python
import requests

r = requests.post(
    "https://api.reefapi.com/hs-code/v1/hs_lookup",
    headers={"x-api-key": REEF_KEY},
    json={
  "code": "8471.30.0100",
  "destination": "US"
},
)
print(r.json()["data"])
FAQ

Have a question? We got answers.

The questions people actually ask before wiring up HS Code & Tariff.

Get a free key →
I looked up a code and import_duty came back null. Why?

Because the code is not declarable. A measured lookup of UK heading 6403 returned declarable false with import_duty null, vat null and a note saying rates are published at the declarable level — plus context[] with 60 child lines to choose from. That is the answer, not a failure: a 4-digit heading is a category, and duty is set per specific line. Walk into context[] and pick the child that matches the goods, then look that up. Do not assume that adding zeros to a heading produces a valid line.

Does a 10-digit code always carry rates?

No. Measured, UK 6109100000 for T-shirts came back declarable false with null rates, while 6403120000 with the same digit count came back declarable true with an 8.0% duty. Declarability is a property of the tariff line in the schedule, not of its length, because some ten-digit codes are themselves intermediate nodes. Always branch on the declarable boolean and never on len(code).

How reliable is the classify action?

Treat it as a shortlist, never as an answer. It is a relevance heuristic over the tariff text — the response says so in confidence_note — and the score reflects search rank, not correctness. A measured UK classification of 'leather shoes for men, leather upper' returned a top candidate at confidence 0.95 with confidence_band 'high' and review_required false, and that candidate was a sports-footwear line: tennis shoes, basketball shoes, gym shoes. High confidence there means a strong text match, not the right code. Use it to narrow to a chapter, then confirm the line with hs_lookup and a broker.

How is the landed cost actually calculated?

Transparently, and the assumptions travel with the answer. A measured UK estimate on a 1,200 value with 80 shipping and an 8.0% duty line returned estimated_duty 96.0 — eight percent of the customs value alone, not of value plus shipping — with VAT computed on value plus shipping plus duty, and total_landed_cost 1,376.0 in a breakdown you can check by hand. Read assumptions[] every time: it states that the general third-country MFN rate was applied for the origin you gave, that trade-preference (FTA) rates, anti-dumping duty and US Section 301/232 surcharges are NOT applied automatically, and that no currency conversion happens — all figures stay in whatever unit you passed.

What does preference_measures tell me?

How many preferential rate measures exist on that line, as a count — 56 on the measured ski-boot code. It is a signal, not a rate: it tells you there is real money to be found if your goods qualify under an FTA, a GSP scheme or a quota, and that the MFN figure you were quoted is the worst case. It does not tell you which ones you qualify for, and we do not guess at that; origin rules are the part that needs a human.

What does an UPSTREAM_HTTP error mean here, and why does retryable differ?

It means the government schedule itself did not answer. Observed against the US side: hs_lookup returned UPSTREAM_HTTP with 'no HTS data for heading 8471 (status 503)' and retryable true, while landed_cost on the same code returned the same underlying failure with retryable false. The difference is deliberate — a lookup is worth retrying because the .gov service may recover in seconds, but a landed-cost estimate has no meaning without a tariff line, so retrying the whole calculation is wasted work. Fix the lookup first, then recompute. During an outage classify can also return zero candidates for that market, which is an empty index rather than an unclassifiable product.

Can I use this to file a customs declaration?

No, and every response says so. The data is pulled from the official published schedules — USITC HTS for the US and HMRC's live Trade Tariff for the UK, both named in source and pinned by schedule_version — but a classification is only binding when the customs authority issues it. Each declarable UK line carries a bti_url pointing at the binding-decision process. Use this to estimate, to compare markets and to check a broker's work; do not use it as the sole basis for an entry.

What is in the hierarchy object?

The full path above your code, which is what you need to explain a classification to somebody. A measured ski-boot lookup returned section XII with its full title, chapter 64 'Footwear, gaiters and the like; parts of such articles', and heading 6403 'Footwear with outer soles of rubber, plastics, leather or composition leather and uppers of leather'. Sections are Roman numerals and chapters are two digits, which is worth knowing before you try to sort them as integers. Alongside it, validity_start and validity_end date the line — a null validity_end means the line is currently in force.

What is the HS Code & Tariff API?

HS Code & Tariff API is a ReefAPI endpoint group for hs code & tariff It returns live JSON through POST requests under /hs-code/v1.

Is the HS Code & Tariff API free to try?

Yes. ReefAPI starts with 1,000 free credits, no card required. HS Code & Tariff calls use the same shared credit balance as every other ReefAPI engine.

Do I need a HS Code & Tariff login or account?

No login to HS Code & Tariff is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.

How fresh is the HS Code & Tariff data?

The page example is captured from a live hs_lookup call, and production requests fetch live data through ReefAPI rather than a static sample.

How many credits does the HS Code & Tariff API use?

HS Code & Tariff actions currently cost 1-8 credits per successful call. Failed or blocked calls are free, and all APIs draw from one credit pool.

Can I call HS Code & Tariff from an AI assistant or MCP client?

Yes. Connect ReefAPI once through MCP and your assistant can call hs-code actions with the same key, credit pool and JSON envelope used by normal REST requests.

36 E-commerce & Marketplaces APIs on the same key

One key, one credit pool, one response envelope. If you are pulling HS Code & Tariff, you are one call away from the rest of the category — no second contract, no second integration.

Need something this API does not do?

Name the endpoint, the field, or a source we do not carry yet. We ship new APIs every week and you would be first to get the key. Real people read every message and reply the same day.

0/4000

No account needed · we reply from [email protected]

Try it on your own data before you pay anything

The call above is the real endpoint, not a recording. A free key gives you 1,000 credits, the other 183 APIs, and the same envelope everywhere.

Endpoints, parameters and credit costs on this page are read from the live catalog and cannot drift from what the API accepts. Field notes were captured on 2026-08-28.