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_typeor 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.
| Version | Adds |
|---|---|
v1 | Guarantee and single-seal tracking reads |
v2 | Movement announcements |
v3 | Bulk 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 calling | Call instead |
|---|---|
GET /etd/{serial_no}/corridor | GET /etd/{serial_no}?include=corridor |
GET /etd/{serial_no}/versions | GET /etd/{serial_no}?include=versions |
GET /etd/{serial_no}/versions/{n} | GET /etd/{serial_no}?version={n} |
GET /etd/{serial_no}/deliveries | GET /etd/{serial_no}?include=deliveries |
GET /etd/{serial_no}/guarantee | GET /etd/{serial_no}?include=guarantee |
GET /etd/{serial_no}/tracking | GET /etd/{serial_no}?include=tracking |
POST /etd/batch | GET /etd?filter=serial_no@@A,B,C |
POST /etd/{serial_no}/exit | POST /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:
| Change | What 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
- Read the Changelog before you upgrade your client.
- Watch the notifications feed for notices about your own integration.