Versioning and changes
How the HTS Pilot API changes - one live version for everyone, dated records of the published contract, what counts as a breaking change and how a client keeps working.
The service runs one version of the API, the latest, for every client. There is no version in the path, no
version header and nothing to pin: a request cannot ask for the behaviour of an earlier date. The OpenAPI
document carries 1.0.0 as its info.version; that number describes the document and does not select behaviour.
Every time the published contract changes, the OpenAPI document of that day is kept as a dated version, and the changelog gets an entry: a summary written by a person, and the exact difference against the version before (operations, parameters, fields and status codes that were added, changed, deprecated or removed, each marked when it breaks existing clients).
The version select of these pages shows the reference as it was on a date: its operations, parameter tables and examples. That is a record of what was published then, for reading the history and for comparing with what an integration was built against. It does not change what the service does: the API always serves the latest version, and the API explorer always calls the live API.
A version records the contract, not its wording. A change to paths, operations, parameters, schemas, types, required fields, lists of values, status codes, headers or authentication gets a new dated version and a changelog entry. A change to descriptions, summaries or example text alone does not: the newest version is refreshed in place.
Changes that a well-written client is not affected by are made as part of normal releases, and appear in the changelog as "added":
- a new operation, a new optional parameter, a new optional field of a request;
- a new field in an answer, at any depth;
- a new value in a list of values that grows with the product: review flag codes, webhook events, entitlement keys, kinds of alert, error codes;
- the wording of a message (
detail, labels, the text of a flag), which is not part of the recorded contract.
Removing or renaming an operation, a parameter, a field or a response header; changing the type or the meaning of a field; making an optional parameter or request field required; letting an answer leave out a field it always had; no longer accepting a value a request could send; changing the status code of a success, or what authenticates a call. An error status added to or dropped from the list of an operation is not breaking. A breaking change is recorded in the changelog, marked as breaking, in the version in which it was released. One change from before the history began is on record in Languages: the questions, the missing information and the legal findings of a lookup moved from the language of the reader to the language of the lookup.
There is no deprecation header, no fixed notice period and no commitment to keep an earlier behaviour available
today. The changelog, with its feed at /changelog.xml, is where changes are announced.
- Ignore fields you do not know. Do not fail on an unknown value of a status, a flag code or an event name: treat it as "other".
- Branch on machine values (
status,decision, thecodeof an error, thecodeof a flag), never on message text. Treat an error code you do not know like its HTTP status. - Follow the changelog feed, and read
/openapi.jsonon this host when you need the current contract: it is generated from the running code. - Verify webhook signatures over the raw bytes, so a new field in a payload does not break verification.
Separately from the API, each tariff schedule is loaded as a version (dataset_version, for example a revision
of the US HTS). A lookup records the version it was classified against, GET /api/datasets lists the loaded
versions, and GET /api/tariff-changes returns what changed between two of them (Tariff data).