Notifications feed
GET /notifications
The notifications feed is everything ITS has to tell your organisation: a declaration handed to your country, an office code you have not registered, a certificate about to expire, an endpoint that has stopped answering.
It needs no setup. There is no address to declare, no credential to exchange and nothing for the Secretariat to approve. If you can call ITS, you can read the feed. It needs the notification:read permission.
It is the same feed your administration's staff see in the ITS portal. Your service account's scope resolves to your own organisation, and it receives exactly what they receive.
What arrives
Switch on notice_key. The keys are a stable contract and do not change.
notice_key | When |
|---|---|
etd.issued, etd.amended, etd.endorsed, etd.state-changed, etd.attachment | A declaration that concerns your country changed |
etd.closed-beyond-coverage | ITS closed a transit that ran beyond its reach |
station.unregistered | A declaration named one of your customs offices that is not in the register |
onboarding.milestone, onboarding.certified, onboarding.production-approved, onboarding.certificate-expiring | Your own onboarding: a sandbox milestone, certification, production access, an expiring certificate |
integration.delivery-failing | ITS cannot deliver announcements to your receiving endpoint |
integration.endpoint-withdrawn | A REC stopped receiving on your behalf and you have no receiving endpoint of your own |
integration.rejections | ITS refused a number of your requests today |
ITS may add keys. Ignore a key you do not recognise.
What a notification carries
| Field | Meaning |
|---|---|
sequence_no | The notification's position in the feed. Store the highest you have processed. |
notice_key | What happened, as a stable key |
category | DECLARATION, REGISTER, ONBOARDING or INTEGRATION |
severity | INFO, ATTENTION or CRITICAL |
subject_type, subject_id | What the notification is about, such as a declaration and its serial number |
title_key, body_key, params | The text as a catalogue key and its parameters |
title, body | The same text in English |
action_kind, action_ref | What can be done about it, such as open-declaration with a serial number |
occurred_at | When it happened |
correlation_id | The correlation id of the request that caused it, where there is one |
read | Whether this caller has marked it read |
If you store notifications, store title_key and params, not only the English title. Otherwise you have decided the language for everyone who reads your copy.
action_kind never carries a link into your application. Map each kind to your own screen, and ignore a kind you do not recognise.
Catch up after an outage
Store the highest sequence_no you have processed. When you come back, ask for everything after it, oldest first:
curl --fail-with-body --silent --show-error \
--cert "$ITS_CLIENT_CERT" --key "$ITS_CLIENT_KEY" \
--header "Authorization: Bearer $ITS_TOKEN" \
"$ITS_GATEWAY_URL/notifications?since_sequence=1874&ascending=true&page-number=1&page-size=50"
Always use ascending=true for a system. It is the order to process events in, and it is the only direction in which paging over a feed that is still growing can neither repeat nor skip a notification. The default order is newest first, because that is what a person wants.
| Parameter | Meaning |
|---|---|
since_sequence | Only notifications after this sequence number |
ascending | true for oldest first. Defaults to false. |
until_sequence | Nothing after this sequence number. Use it to pin a newest-first listing while you page. |
unread_only | Only what this caller has not marked read. Defaults to false. |
page-number, page-size | Ordinary paging, as on every ITS listing |
filter | See below |
Filter the feed
Filters use the same field<operator>value grammar as the declaration list, repeated and combined:
?filter=category::DECLARATION&filter=severity@@ATTENTION,CRITICAL&filter=occurred_at%3E%3A2026-09-01
| Field | Operators | Value |
|---|---|---|
category | :: @@ | DECLARATION, REGISTER, ONBOARDING, INTEGRATION |
severity | :: @@ | INFO, ATTENTION, CRITICAL |
subject_type | :: | A subject type |
subject_id | :: | A subject id, such as a serial number |
occurred_at | >: <: | A date, such as 2026-09-01. The bounds cover whole days. |
Percent-encode > and <. A field the feed does not have is refused with 400 VAL-ETD-034, never answered with an empty page.
What to alert on
INFOis the record: routine corridor movement, in volume.ATTENTIONmeans your administration has something to do.CRITICALmeans something is already failing because it has not been done.
Raise alerts in your own system on ATTENTION and CRITICAL. A corridor produces enough INFO to make an unfiltered alert useless.
Other operations
| Operation | Purpose |
|---|---|
GET /notifications/summary | Unread and actionable counts, and the latest few notifications |
GET /notifications/{sequence_no} | One notification. 404 both when it does not exist and when it is not yours. |
POST /notifications/{sequence_no}/read | Mark one read for this caller. Needs notification:write. |
POST /notifications/read-all | Mark everything read for this caller. Needs notification:write. |
GET /notifications/stream | A server-sent event stream of new notifications, for a console |
Read state belongs to the caller, not the organisation. A colleague still sees a notification as unread after you mark it read.
The stream is a convenience, not a delivery guarantee: a dropped connection loses what arrived while it was down. A system that must miss nothing polls the listing with since_sequence.
The feed and a receiving endpoint
The feed is free and always there. A receiving endpoint is faster: ITS pushes each announcement to your system within seconds of the act, which matters at a border. It costs an address, a credential and the Secretariat's approval.
Neither replaces the other. A country with a receiving endpoint has both.