Skip to main content

Changes to the API

This page explains how ITS changes and how to keep your integration working when it does. The Changelog lists what changed and when. The ITS API reference always shows the current contract.

Build for additive change

Some changes add something without breaking what is there. Build your client so it keeps working when they arrive:

  • Ignore response fields you do not recognise. New fields appear beside existing ones. The document's own keys never move.
  • Treat code lists as open. A new notice_key, action_kind, change_type or error code can appear. Log a value you do not recognise instead of failing.
  • Send only the fields in the contract. A field ITS does not read is ignored, not refused, so never rely on one being processed.
  • Match on error codes, not messages. Codes are stable. Messages may change or be translated.

A retired error code is never reused. A code in an old log still means what it meant.

The partner contract is versioned per country

The endpoints your systems implement for ITS follow the partner contract. Its version is recorded for each country separately, so v1, v2 and v3 countries work side by side and upgrading is never a flag day.

VersionAdds
v1Guarantee and single-seal tracking reads
v2Movement announcements
v3Bulk positions and seal history for tracking platforms

A country on an earlier version keeps working exactly as before. See Receiving announcements.

Endpoints that moved

If you integrated before August 2026, several endpoints moved. Their old paths mostly still exist under another method, so an old call answers 405 (ERR-022), not 404.

You were callingCall instead
GET /etd/{serial_no}/corridorGET /etd/{serial_no}?include=corridor
GET /etd/{serial_no}/versionsGET /etd/{serial_no}?include=versions
GET /etd/{serial_no}/versions/{n}GET /etd/{serial_no}?version={n}
GET /etd/{serial_no}/deliveriesGET /etd/{serial_no}?include=deliveries
GET /etd/{serial_no}/guaranteeGET /etd/{serial_no}?include=guarantee
GET /etd/{serial_no}/trackingGET /etd/{serial_no}?include=tracking
POST /etd/batchGET /etd?filter=serial_no@@A,B,C
POST /etd/{serial_no}/exitPOST /etd/{serial_no}/endorsements/exit with next_country_code, or POST /etd/{serial_no}/endorsements/discharge to close the transit

An include nests its answer under its own name, so the response shape moves with the URL. What was data.stops is now data.corridor.stops. The status code does not change, so check the shape when you migrate, not only the status.

Other changes that fail quietly

These changes give you no error at all, because an unknown query parameter or a discarded field is ignored:

ChangeWhat an old client sees
GET /etd no longer takes cursor or limit. Use page-number, page-size and a created_at watermark.Page one at the default size, and 200
The named list parameters state=, departure_country=, destination_country=, created_from= and created_to= were replaced by filter.An unfiltered list
endorsed_at, a stamp time you sent, is gone. ITS records when it received each stamp.Nothing. The field is not read.
Totals, td_date, the point of loading and transport_mode are assigned by ITS.Nothing. The fields are discarded.
ITS no longer validates TINs. tin_scheme and country on a party are ignored, and GET /api/reference/tin-schemes answers 404.Nothing breaks

The lifecycle gained a release act

The lifecycle now has three acts per country: entry, release (depart) and exit. A declaration that is registered has not left, and an exit without a depart before it is refused. EXITED became DISCHARGED, closing a transit became its own discharge act, and every act fires a transition. See Lifecycle and stamps.

Stay informed