See it in action

Get a working API response in under 60 seconds.

What can you do with this API?

A plain-English overview of every query type. Click any card to jump to the full documentation and code example.

01 — US, Canada & Mexico
Look up a tariff code
Give it any US HTS, Canadian, or Mexico TIGIE tariff number and get back the full record: duty rate, trade agreement exemptions, description, and any active Section 301 or 232 surcharges.
02 — US, Canada & Mexico
Search by keyword
Don’t know the exact code? Search “steel” or “medical equipment” and get a list of matching tariff entries with their codes and rates.
03 — US, Canada & Mexico
Retrieve a full chapter
The tariff schedule is organized into 99 chapters by product category — Chapter 84 is machinery, Chapter 62 is apparel, Chapter 27 is petroleum. Pull every code in a chapter as a single JSON array. Useful for seeding a local database or building a code picker.
04 — US, Canada & Mexico
Track what changed
A nightly process compares the latest USITC and CBSA schedules against the prior version. Any additions, removals, or rate changes are recorded with a timestamp. Returns an empty array when the schedule is stable — that’s correct, not a bug.
05 — Canada only
Find goods that enter Canada duty-free from the US
Filter the Canadian schedule by the UST (United States Tariff) column to see which goods qualify for preferential entry under CUSMA/USMCA. Useful for compliance tools serving importers moving goods across the US-Canada border.
Webhooks — Tier 3 & 4
Push alerts on tariff changes
Register an HTTPS endpoint and receive a signed POST the night a change is detected. Covers US HTS and CA Customs Tariff. No polling required.

Scope note: TradeFacts returns tariff data for a given HTS or Canadian tariff code — the classification of goods to a code (applying GRI rules, determining essential character, resolving competing provisions) is performed by your broker, customs consultant, or compliance team. This API is the data layer; the classification decision stays with the human.

Python SDK

Drop tradefacts.py into your project. No manual header construction required.

pip install requests
from tradefacts import TradeFacts
client = TradeFacts("your-api-key")
record  = client.hts("0901.11.00")
record  = client.ca("0901.11.00")
results = client.search("green coffee")
changes = client.changes()

Download tradefacts.py →

Base URL

https://tradefacts.io

All API endpoints are served over HTTPS. HTTP requests are redirected to HTTPS.

Authentication

All endpoints (except /request-access) require a valid API key in the X-API-Key request header.

curl
curl https://tradefacts.io/api/hts/8471.30.01.00 \
  -H "X-API-Key: your_api_key_here"
PowerShell
Invoke-WebRequest -Uri "https://tradefacts.io/api/hts/8471.30.01.00" `
  -Headers @{"X-API-Key"="your_api_key"}

Missing or invalid key returns HTTP 401. Expired or cancelled subscription, or a plan attempting to access a restricted endpoint, returns HTTP 403.

Error Codes

StatusMeaning
200Success
401Missing or invalid API key
403Access denied — trial expired, subscription cancelled, or plan does not include this endpoint (e.g. Tier 1 accessing CA data, Tier 1-3 accessing IEEPA overlay)
404Code not found in dataset
422Invalid request parameters
500Internal server error

Error Response Format

All error responses return JSON with a detail field describing the error.

{ "detail": "Invalid or missing API key" }

Rate Limits

No hard rate limits are enforced. If syncing the full dataset, batch chapter retrieval during off-peak hours.


HTS Code Lookup

GET /api/hts/{code} Auth required

Returns a single HTS record by its full code. The code can be passed with or without periods.

ParameterTypeDescription
coderequiredstringFull HTS code, e.g. 0101.30.00.00 or 0101300000
curl
curl https://tradefacts.io/api/hts/8471.30.01.00 \
  -H "X-API-Key: your_api_key"
PowerShell
Invoke-WebRequest -Uri "https://tradefacts.io/api/hts/8471.30.01.00" `
  -Headers @{"X-API-Key"="your_api_key"}
JSON Response
{
  "htsno": "8471.30.01.00",
  "indent": "1",
  "description": "Portable automatic data processing machines, weighing not more than 10 kg, consisting of at least a central processing unit, a keyboard and a display",
  "superior": null,
  "units": ["No."],
  "general": "Free",
  "special": "",
  "other": "35%",
  "footnotes": [],
  "quotaQuantity": null,
  "additionalDuties": null
}

Chapter Retrieval

GET /api/chapter/{chapter} Auth required

Returns all HTS records for a given two-digit chapter.

ParameterTypeDescription
chapterrequiredstringTwo-digit chapter, e.g. 01, 76, 99
curl
curl https://tradefacts.io/api/chapter/76 \
  -H "X-API-Key: your_api_key"
PowerShell
Invoke-WebRequest -Uri "https://tradefacts.io/api/chapter/76" `
  -Headers @{"X-API-Key"="your_api_key"}

Change Log

GET /api/changes Auth required

Full history of detected changes to the US HTS dataset. Updated nightly at 02:00 UTC.

curl
curl "https://tradefacts.io/api/changes" \
  -H "X-API-Key: your_api_key"
PowerShell
Invoke-WebRequest -Uri "https://tradefacts.io/api/changes" `
  -Headers @{"X-API-Key"="your_api_key"}

IEEPA Overlay

The IEEPA Overlay provides provisional tariff rates sourced directly from Federal Register proclamations — bridging the gap between a new executive order and USITC codification, which can lag by days to weeks. Rates are manually verified by TradeFacts editorial before publication and are clearly marked PROVISIONAL. Always verify with CBP before filing.

The overlay is maintained in near-real time: the FR monitor checks for new presidential proclamations every 4 hours. When a new tariff action is detected, proposed rates are extracted and reviewed before going live. The ieepa_overlay_notice field on base HTS lookups flags when overlay entries exist that are not yet reflected in HTS footnotes.

GET /api/ieepa/{code} Auth required

Look up the current IEEPA provisional rate for a specific Chapter 99 code. Returns the overlay rate, source Federal Register document, verification date, and a machine-readable rate_status: "PROVISIONAL" field.

ParameterTypeDescription
coderequiredstringChapter 99 HTS code, e.g. 9903.01.25
JSON Response
{
  "code": "9903.01.25",
  "rate_provisional": "10%",
  "description": "Temporary import surcharge...",
  "source_document": "FR Doc 2026-03824",
  "effective_date": "2026-02-24",
  "verified_date": "2026-03-31",
  "verified_by": "TradeFacts editorial",
  "rate_status": "PROVISIONAL",
  "disclaimer": "Sourced from Federal Register..."
}
GET /api/discrepancies Auth required

Returns all known discrepancies between the IEEPA overlay and the published HTS schedule. Three discrepancy types are detected:

TypeMeaning
rate_differsOverlay rate differs from the HTS Chapter 99 rate for the same code — the overlay reflects a more recent FR proclamation not yet codified by USITC.
footnote_gapOverlay code exists in the HTS but is not referenced in any base code footnote — goods subject to this rate will not have it surfaced by standard HTS lookups. The ieepa_overlay_notice field on code lookups flags this condition.
hts_code_missingOverlay code does not yet exist in the HTS index — a newly created Chapter 99 code ahead of USITC codification.

The discrepancy list grows as FR proclamations are approved into the overlay. An empty result means no discrepancies are currently tracked — not that none exist. Overlay coverage expands with each approved FR document.


Canada Customs Tariff API

Tier 2, 3 & 4

Full 2026 Canadian Customs Tariff sourced from CBSA — 22,461 records across all 99 chapters (11,668 primary 8-digit tariff items plus 10,793 10-digit statistical subdivisions). Every record includes the MFN rate plus all applicable preferential treatment columns from Canada's full FTA network: CUSMA/USMCA, CETA (EU), CPTPP, Canada–UK, and 15 bilateral agreements. Use the treatment parameter on search and chapter endpoints to filter by any agreement code.

Canada endpoints mirror the US HTS endpoints and use the same X-API-Key authentication. The base path is /api/ca/ instead of /api/hts/.

Note: Retaliatory surtax overlay (separate CBSA notices on top of MFN rates) is on the roadmap and not yet included.

CA Tariff Lookup

GET /api/ca/{code} Auth required

Returns a single Canadian tariff record by its full tariff code.

ParameterTypeDescription
coderequiredstringFull CA tariff code, e.g. 0101.21.00
curl
curl https://tradefacts.io/api/ca/0101.21.00 \
  -H "X-API-Key: your_api_key"
PowerShell
Invoke-WebRequest -Uri "https://tradefacts.io/api/ca/0101.21.00" `
  -Headers @{"X-API-Key"="your_api_key"}

CA Chapter Retrieval

GET /api/ca/chapter/{chapter} Auth required

Returns all Canadian tariff records for a given two-digit chapter.

ParameterTypeDescription
chapterrequiredstringTwo-digit chapter, e.g. 84
treatmentoptionalstringFilter by preferential treatment code, e.g. CEUT, CPTPT, UST. See treatment codes table.
curl
curl https://tradefacts.io/api/ca/chapter/84 \
  -H "X-API-Key: your_api_key"
PowerShell
Invoke-WebRequest -Uri "https://tradefacts.io/api/ca/chapter/84" `
  -Headers @{"X-API-Key"="your_api_key"}

UST Rate Filter

GET /api/ca/ust Auth required

Filter Canadian tariff records by UST (United States Tariff) rate — the CUSMA/USMCA preferential rate applied to US-origin goods.

ParameterTypeDefaultDescription
rateoptionalstringUST rate value, e.g. Free, 6.5%
limitoptionalinteger100Max results. Maximum: 500.
curl
# Get all tariff lines where US goods enter Canada duty-free
curl "https://tradefacts.io/api/ca/ust?rate=Free" \
  -H "X-API-Key: your_api_key"
PowerShell
Invoke-WebRequest -Uri "https://tradefacts.io/api/ca/ust?rate=Free" `
  -Headers @{"X-API-Key"="your_api_key"}

CA Change Log

GET /api/ca/changelog Auth required

Full history of detected changes to the Canadian Customs Tariff dataset. Updated nightly at 02:30 UTC.

curl
curl "https://tradefacts.io/api/ca/changelog" \
  -H "X-API-Key: your_api_key"
PowerShell
Invoke-WebRequest -Uri "https://tradefacts.io/api/ca/changelog" `
  -Headers @{"X-API-Key"="your_api_key"}

Mexico Tariff (TIGIE) Tier 2+

Full 2026 Mexico TIGIE (Tarifa de la Ley de los Impuestos Generales de Importación y de Exportación) sourced from SNICE (Secretaría de Economía) — 8,183 fracciones arancelarias across 97 chapters. Includes the IGI (general import rate / MFN), export rate, and unit of measure for every fraction. Updated when SNICE publishes a new bulk release. All descriptions are in Spanish as published by the official authority.

Mexico endpoints mirror the US and Canada endpoints and use the same X-API-Key authentication. The base path is /api/mx/.

USMCA/T-MEC preferential rates: Under the T-MEC agreement, virtually all US and Canadian origin goods enter Mexico at 0% duty. These preferential rates are governed by the T-MEC treaty and are not stored as per-fraction columns in the TIGIE bulk data. The IGI field reflects the MFN (general) rate applicable to non-FTA origin goods.

MX Lookup

GET /api/mx/{code} Auth required

Look up a single Mexico TIGIE fraccion arancelaria. Accepts with or without dots — 0101.21.01 and 01012101 both work.

curl
curl "https://tradefacts.io/api/mx/7201.10.01"   -H "X-API-Key: your_api_key"
PowerShell
Invoke-WebRequest -Uri "https://tradefacts.io/api/mx/7201.10.01" `
  -Headers @{"X-API-Key"="your_api_key"}
Response
{
  "fraccion": "7201.10.01",
  "chapter": "72",
  "description": "Fundición en bruto sin alear con un contenido de fósforo inferior al 0,5% en peso",
  "unit": "Kg",
  "igi": "35",
  "ige": "Ex."
}

MX Chapter

GET /api/mx/chapter/{chapter} Auth required

All Mexico TIGIE records for a given chapter (01–98). Returns the full array of fracciones for that chapter.

curl
curl "https://tradefacts.io/api/mx/chapter/72"   -H "X-API-Key: your_api_key"

MX Change Log

GET /api/mx/changelog Auth required

History of detected changes to the Mexico TIGIE dataset. Updated when SNICE publishes a new bulk release (checked nightly at 03:00 UTC). Returns an empty array when no changes have been detected yet.

curl
curl "https://tradefacts.io/api/mx/changelog"   -H "X-API-Key: your_api_key"

Webhooks Tier 3 & 4

Webhooks eliminate polling. Instead of querying /api/changes each night, register an HTTPS endpoint once. TradeFacts POSTs a signed payload automatically whenever the nightly update detects a rate change — US HTS or Canadian Customs Tariff.

Delivery fires after each nightly ingest: ~02:00 UTC for US changes, ~02:30 UTC for CA changes. No changes detected = no POST sent.

Every POST is signed with HMAC-SHA256 using the secret you set at registration — the same pattern used by Stripe and GitHub webhooks.

Tier 3 & 4. Webhooks require Tier 3 ($399/month) or Tier 4 ($499/month). View pricing →

Register a Webhook Endpoint

POST /api/webhook/register Tier 3 & 4

Register or replace your webhook endpoint. Supply any secret you choose (16+ characters). Calling this again overwrites the previous URL and secret.

FieldTypeRequiredNotes
urlstringYesHTTPS only
secretstringYesMin 16 chars. You choose it. Store it securely.
curl
curl -X POST "https://tradefacts.io/api/webhook/register" \
  -H "X-API-Key: your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://your-app.com/hooks/tradefacts","secret":"your-secret-min-16-chars"}'

Response on success:

JSON
{
  "status": "registered",
  "url": "https://your-app.com/hooks/tradefacts",
  "note": "Fires nightly 02:00-02:30 UTC when changes detected."
}

Webhook Payload Schema

Every POST body is JSON. The top-level envelope:

FieldTypeDescription
sourcestring"US" or "CA"
eventstringAlways "tariff_change"
timestampstringISO 8601 UTC delivery time
change_countintegerNumber of changed records in this payload
changesarrayArray of change objects (see below)

Each object in changes has a type field:

typeFields present
modifiedcode, description, changed_fields — object with {field: {old, new}} pairs for every changed field
addedcode, description, plus general/units (US) or mfn/ust (CA)
removedcode, description

Example payload (US rate modification):

JSON
{
  "source": "US",
  "event": "tariff_change",
  "timestamp": "2026-03-19T02:14:37Z",
  "change_count": 1,
  "changes": [
    {
      "type": "modified",
      "code": "7606.12.30",
      "description": "Of aluminum alloys, not alloyed",
      "changed_fields": {
        "additionalDuties": {
          "old": "25% (Section 232)",
          "new": "25% (Section 232) + 10% (IEEPA)"
        }
      }
    }
  ]
}

Verifying the Signature

Every POST includes an X-TradeFacts-Signature header. The value is sha256=<hex> — HMAC-SHA256 of the raw request body using your secret.

Always verify before processing. Use a constant-time comparison to prevent timing attacks.

Python
import hmac, hashlib

def verify_tradefacts_signature(raw_body: bytes, secret: str, header: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(), raw_body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, header)

# Flask example
from flask import request, abort
@app.route("/hooks/tradefacts", methods=["POST"])
def handle_webhook():
    sig = request.headers.get("X-TradeFacts-Signature", "")
    if not verify_tradefacts_signature(request.get_data(), SECRET, sig):
        abort(400, "Invalid signature")
    payload = request.get_json()
    for change in payload["changes"]:
        print(change["code"], change.get("changed_fields", {}))
    return "", 200
Node.js
const crypto = require("crypto");

function verifySignature(rawBody, secret, header) {
  const expected = "sha256=" + crypto
    .createHmac("sha256", secret)
    .update(rawBody)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(header)
  );
}

// Express example
app.post("/hooks/tradefacts", express.raw({ type: "application/json" }), (req, res) => {
  const sig = req.headers["x-tradefacts-signature"] || "";
  if (!verifySignature(req.body, process.env.TRADEFACTS_SECRET, sig)) {
    return res.status(400).send("Invalid signature");
  }
  const payload = JSON.parse(req.body);
  payload.changes.forEach(c => console.log(c.code, c.changed_fields));
  res.sendStatus(200);
});

Retry behaviour: If your endpoint does not respond with HTTP 2xx, TradeFacts retries 3 times with exponential backoff (5s, 15s, 45s). After all attempts fail, Rick receives an alert email.

Idempotency: Each nightly run generates one POST per source (US, CA). There is no deduplication guarantee across retries — your endpoint should be idempotent (safe to receive the same payload twice).

US HTS Data Schema

All US HTS endpoints return records conforming to this schema.

Rate field format reference

The general, special, and other fields are free-text strings from USITC. Parsers must handle all of the following formats:

FieldTypeNotes
htsnostringFull HTS code with dots, e.g. 0101.30.00.00
indentstringHierarchy depth as normalized string integer, 0–9
descriptionstringCommodity description text
superiorstring|nullParent HTS code if applicable
generalstringMFN (Most Favored Nation) duty rate. Empty string for header/section records. See rate format reference below.
specialstringFTA preferential rates with country codes in parentheses, e.g. Free (AU,KR,SG) or 17.1% (AU). Empty string when no preferential rates apply. May contain inconsistent whitespace within country code lists. See trade agreement codes below.
otherstringColumn 2 rate — applies only to goods from Cuba and North Korea. Same format as general. No change in Chapter 99 records.
unitsarrayUnit of quantity codes
footnotesarrayApplicable endnotes
quotaQuantitystring|nullTariff-rate quota quantity if applicable
additionalDutiesstring|nullSupplementary specific duty on top of the general rate, e.g. 66.6¢/kg. null when none. Whitespace-only strings also indicate no additional duty — use .strip() before evaluating.
chapter_99_additional_dutiesarray|nullChapter 99 cross-references parsed from footnotes. Present when the record (or its 8-digit parent) references a Chapter 99 additional duty. Each element: htsno (string), description (string), additional_duty (string — e.g. "The duty provided in the applicable subheading + 25%"), applies_to (array of rate columns, e.g. ["general"]). Absent when no Chapter 99 cross-references exist.
rate_inherited_fromstring|nullPresent on 10-digit statistical subdivision records that carry no rate of their own. Contains the 8-digit parent code from which general, special, other, and footnotes were inherited (e.g. "9403.60.80"). Absent for directly-rated records.
FormatExampleNotes
Empty string""Header or section record — no classifiable rate. Skip for rate lookups.
Free"Free"Zero duty.
Ad valorem"3%", "14.9%"Percentage of customs value. Strip % and parse as float.
Specific — cents"1¢/kg", "68¢/head"Fixed amount per unit. Requires declared quantity to compute duty payable.
Specific — dollars"$1.44 each", "$1.34/1000"Dollar-denominated per-unit rate. Same computation requirement as cents-specific.
Compound"$1.104/kg + 14.9%"Specific rate plus ad valorem. Both components must be computed and summed.
Chapter 99 formula"The duty provided in the applicable subheading + 25%"IEEPA/301/232 surcharge stacked on base HTS rate. The chapter_99_additional_duties field surfaces these automatically on every affected record — no separate Chapter 99 lookup required.
No change"No change"Chapter 99 record that does not modify the rate. Ignore for rate computation.

Note: Chapter 99 IEEPA and Section 301 rates reflect the USITC schedule and may lag recent executive orders by days to weeks. The chapter_99_additional_duties field surfaces all cross-references present in the published schedule. For the most current IEEPA rates ahead of USITC codification, use GET /api/ieepa/{code} to look up a specific Chapter 99 code, or GET /api/discrepancies to see all known gaps between the overlay and the published HTS schedule.

CA Data Schema

Canadian tariff records include the tariff code, description, and all 23 preferential rate columns from the CBSA schedule.

FieldTypeNotes
tariffstringCanadian tariff code. 8-digit primary items (e.g. 0101.21.00) or 10-digit statistical subdivisions (e.g. 0101.21.00.00). Both formats are accepted by /api/ca/{code}. Search returns 8-digit items by default.
descriptionstringCommodity description text
mfnstringMost Favoured Nation rate
generalstringGeneral Tariff rate (non-preferential, non-MFN)
uomstringUnit of measure
eff_datestringEffective date of the tariff item (YYYY-MM-DD)
footnotestringCBSA footnote reference if applicable
preferentialobjectObject containing all applicable preferential rate columns keyed by treatment code. Up to 23 keys: UST, MXT, CEUT, CPTPT, UKT, UAT, KRT, LDCT, GPT, CCCT, IT, CT, CRT, PT, COLT, JT, PAT, HNT, CIAT, NT, SLT, NZT, AUT. Empty object for header/section records. See treatment codes table.

Canadian Preferential Treatment Codes

The preferential object in Canadian tariff records contains rates keyed by treatment code. Pass any code to the treatment parameter on /api/ca/search or /api/ca/chapter/{chapter} to filter records with a rate under that agreement.

CodeAgreementCountries covered
USTUnited States Tariff (CUSMA/USMCA)United States
MXTMexico Tariff (CUSMA/USMCA)Mexico
CEUTCanada–European Union Tariff (CETA)EU 27 member states
CPTPTCPTPP TariffJapan, Vietnam, Malaysia, Singapore, Brunei, Australia, New Zealand, Peru, Chile, Mexico
UKTUnited Kingdom Tariff (Canada–UK TCA)United Kingdom
UATUkraine–Canada Agreement Tariff (CUFTA)Ukraine
KRTKorea Tariff (Canada–Korea FTA)South Korea
LDCTLeast Developed Country TariffUN-designated LDCs
GPTGeneral Preferential TariffDeveloping countries (UNCTAD list)
CCCTCommonwealth Caribbean Countries TariffCARICOM member states
ITCanada–Israel Agreement TariffIsrael
CTCanada–Chile Free Trade Agreement TariffChile
CRTCosta Rica Tariff (Canada–CCRFTA)Costa Rica
PTCanada–Peru FTA TariffPeru
COLTColombia Tariff (Canada–Colombia FTA)Colombia
JTJordan Tariff (Canada–Jordan FTA)Jordan
PATPanama Tariff (Canada–Panama FTA)Panama
HNTHonduras Tariff (Canada–Honduras FTA)Honduras
CIATCanada–Central America TariffEl Salvador, Guatemala, Nicaragua
NTNicaragua TariffNicaragua
SLTEl Salvador TariffEl Salvador
NZTNew Zealand Tariff (CPTPP bilateral)New Zealand
AUTAustralia Tariff (CPTPP bilateral)Australia

Trade Agreement Codes

The special field in US HTS records contains preferential rates with trade agreement codes in parentheses.

CodeAgreement
A, A+Generalized System of Preferences (GSP)
AUUS–Australia FTA
BHUS–Bahrain FTA
CAUSMCA (Canada)
CLUS–Chile FTA
COUS–Colombia TPA
ILUS–Israel FTA
JOUS–Jordan FTA
KRUS–Korea FTA (KORUS)
MAUS–Morocco FTA
MXUSMCA (Mexico)
OMUS–Oman FTA
PAUS–Panama TPA
PEUS–Peru TPA
SGUS–Singapore FTA

Ready to integrate?

Request a free trial key and be querying the API within the hour.

Tariff Wire

Stay ahead of US, Canada & Mexico tariff changes

Weekly digest for compliance teams and developers. Plain English, no noise.

No spam. Unsubscribe any time.