The US International Trade Commission publishes the Harmonized Tariff Schedule as a free, publicly accessible REST API. If you are building trade compliance software and you just discovered this, your first reaction is probably: great, problem solved.

It isn't. Not for production use. The USITC API is a legitimate starting point for exploration and prototyping, but every engineering team that has tried to build a production integration directly against it has eventually built a layer on top of it — or replaced it entirely. This post explains exactly why, with specifics, so you can make an informed decision about your architecture before you invest engineering time finding out the hard way.

What the USITC API Does Well

To be fair: the USITC API is genuinely useful for what it is. It exposes the full HTS dataset, it's free, it requires no authentication, and it covers all 99 chapters. For a developer who needs to look up a tariff code interactively, or who is building a quick internal tool to check rates, it works fine.

The problems emerge when you try to build something that other people depend on, that needs to stay accurate over time, and that needs to handle the full complexity of the tariff schedule reliably.

Problem 1: The Schema Changes Without Notice

The USITC updates the HTS schedule periodically, and when they do, they sometimes change the structure of the data — field names, nesting, how certain values are represented. There is no versioning in the API response that would let your application detect this. There is no changelog. There is no notification mechanism.

Your pipeline will parse the response correctly until one day it doesn't. The failure mode is often silent: the data continues to load, but fields your application depends on come back empty or miskeyed. You find out when a user reports incorrect data, or when your own quality checks catch it — if you have them.

This is not a theoretical risk. Teams that have run production pipelines against USITC directly have encountered schema shifts in both 2024 and 2025 schedule releases. The fix each time is straightforward, but it requires someone to notice, diagnose, and patch it. That is engineering time, and it happens on USITC's schedule, not yours.

Problem 2: Chapter 99 Requires Special Handling

The USITC API returns Chapter 99 data, but Chapter 99 is structurally different from every other chapter in the schedule. Most chapters describe goods in a hierarchical product taxonomy. Chapter 99 describes trade actions — Section 232, Section 301, exclusions, suspensions — and its entries reference heading ranges in other chapters rather than describing products directly.

If you query the USITC API for an HTS code in Chapter 72 (steel) and parse only that result, you will get the base MFN rate. You will not automatically get the applicable Section 232 additional duty. That lives in Chapter 99, and connecting it to the Chapter 72 code requires a separate query and a join that the API does not perform for you.

For many trade compliance applications, returning only the base MFN rate is a compliance error. The additional duties are real, they are significant, and they are what importers are actually paying. An application that ignores Chapter 99 is giving users incomplete information.

Problem 3: No Change Detection

The USITC API has no endpoint that returns what changed since a given date. There is no /changes endpoint, no diff mechanism, no event feed. If you want to know whether anything in the schedule has been updated, you have to fetch the entire dataset and diff it yourself against your stored version.

For a dataset with over 32,000 records across 99 chapters, a full fetch-and-diff on every poll cycle is not a lightweight operation. Most teams end up polling less frequently than they should as a result — which means their applications run on stale data between polls. In a period of active trade policy changes, that window can matter.

Problem 4: No Webhook or Push Mechanism

Downstream of change detection is the question of what you do with it. If your application needs to notify users when a tariff code affecting their products changes, or if you need to trigger a recalculation in your system, you need to know about changes when they happen — not on your next poll cycle.

The USITC API has no push mechanism. You poll it, or you don't find out. Building a webhook layer on top of a polling architecture requires you to maintain the diff logic, the change store, and the delivery mechanism yourself. That is a non-trivial amount of infrastructure for a feature that is table stakes for a production trade compliance product.

Problem 5: Availability and Rate Limits Are Not Guaranteed

The USITC API is a government service. It is not operating under a commercial SLA. It has experienced downtime. It has responded slowly during periods of high load — which tend to coincide with periods of active trade policy change, when your users are most likely to be querying it.

If your application's availability depends directly on USITC's availability, you have introduced a dependency you cannot control and cannot escalate. Building a caching layer between your application and USITC is the obvious mitigation, but once you have built that layer, you have essentially built what we are describing here: a separate data pipeline that you now own and maintain.

The Hidden Cost: Engineering Maintenance

Each of the problems above has a workaround. You can build schema version detection. You can write a Chapter 99 join. You can implement your own change detection. You can manage your own cache. None of these is an impossible engineering problem.

The issue is that once you have built all of them, you are maintaining a trade data infrastructure layer that is not your product. It requires attention every time USITC makes a change. It requires someone on your team to have enough HTS knowledge to validate that the data is correct. It requires monitoring and alerting. It competes with your actual product roadmap for engineering time.

For a team whose core product is trade compliance software, this is overhead. The pipeline is a cost center, not a differentiator.

What a Production-Ready HTS Integration Actually Needs

Capability USITC API directly TradeFacts.io
Full HTS dataset (32,000+ records) Yes Yes
Stable schema across USITC updates No Yes
Chapter 99 additional duties resolved Manual join required Yes
Nightly updates with safety checks No Yes
Change detection endpoint No Yes — /changes
Webhook push on tariff changes No Yes — Tier 2
Commercial availability SLA No Yes
Cost Free $199–$399/month

When to Use USITC Directly

This is not an argument that the USITC API has no value. There are valid use cases for querying it directly:

If you are building a product that other people pay for, that makes decisions based on current duty rates, or that needs to alert users to changes — you need more than what the USITC API provides out of the box.

The analogy that holds: Stripe didn't build a new banking system. They built a stable, reliable, well-documented layer on top of the existing banking infrastructure so that engineering teams didn't have to. The USITC is the banking system. You probably shouldn't integrate with it directly in production.

TradeFacts.io is that layer for HTS data. We ingest the full schedule nightly, normalize the schema, resolve Chapter 99 additional duties, run safety checks before overwriting live data, and expose it all through a clean JSON API. Your integration works the same way after a USITC format change as it did before. The /changes endpoint tells you exactly what moved and when. 60-day free trial, no credit card.

Stop rebuilding the pipeline. Start a free trial.

60-day free trial, no credit card required. Full HTS dataset, nightly updates, stable schema, change detection included.

Request API Access