---
title: "An API change announced ahead of its effective date."
method: POST
path: "apiChangeAnnounced"
---

# An API change announced ahead of its effective date.

`POST apiChangeAnnounced` (webhook)

## Payload

- WebhookDeliveryEnvelope: Every queued webhook delivery, test pings included, is this envelope POSTed to your endpoint. Headers: X-TrackingMCP-Event (the type), X-TrackingMCP-Delivery (equals body id), X-TrackingMCP-Signature: sha256=hex(HMAC-SHA256(secret, raw body)) where secret is the one returned ONCE at registration. Verify the signature before trusting the payload. Answer any 2xx; a non-2xx or 10-second timeout is retried after 10s, 1m, 5m, 30m and 2h, then marked dead after the sixth failed attempt (about a 2h36m retry window). Delivery is at-least-once, duplicates are possible, and ordering is not guaranteed; deduplicate by delivery id and fetch canonical shipment state. There is no replay endpoint. Enqueueing shipment_updated is currently best-effort, so REST reconciliation/polling remains required after receiver or platform outages. After 20 consecutive failed deliveries the endpoint is disabled automatically; one success resets the counter. Alert events can be suppressed for 24 hours by their alert policy; shipment_updated is emitted only for a newly persisted material change.
  - `id` string, uuid, required: Delivery id. Equals the X-TrackingMCP-Delivery header.
  - `type` union, required: A WebhookEventType, or `ping` for a test delivery.
    - 'api_change_announced' | 'container_arrived' | 'container_available' | 'container_delivered' | 'container_misrouted' | 'customs_hold' | 'demurrage_started' | 'demurrage_warning' | 'eta_changed' | 'schedule_disruption' | 'shipment_updated' | 'vessel_departed' | 'vessel_rollover': A subscribable webhook event. `shipment_updated` is the general push signal for REST reconciliation: fresh carrier persistence added movements or changed a core shipment summary, and the receiver should fetch the canonical shipment resource. Shipment lifecycle alerts remain more specific. `api_change_announced` is platform lifecycle and is better wired to CI or an on-call channel.
    - 'ping'
  - `occurred_at` string, date-time, required
  - `data` union, required: Shape depends on `type`.
    - WebhookStatusEventData: `data` for the status family: container_arrived, container_available, container_delivered, customs_hold, vessel_departed, demurrage_started, demurrage_warning. The demurrage figures are null unless demurrage alerting is armed and applicable.
      - `container_id` string, uuid, required: Our internal shipment UUID. Not a shipping reference; useful only if you store our ids.
      - `identifier` string, nullable: The reference the shipment is tracked by: a container number, a bill of lading or a booking number, whichever it was added with.
      - `identifier_type` 'container_id' | 'bill_of_lading' | 'booking' | 'null', nullable: What kind of reference `identifier` is. Null when unknown (shipments recorded before the type was stored). Additive field, added 2026-08-19; absent on deliveries produced by older builds.
      - `previous_status` 'pre_departure' | 'in_transit' | 'at_transshipment' | 'at_anchor' | 'at_berth' | 'arriving' | 'discharged' | 'customs_hold' | 'available' | 'delivered' | 'returned_empty' | 'cancelled' | 'unknown', required: Derived container status (from `GET /v1/containers/{id}`). Ocean lifecycle order — `discharged` → `available` → `delivered` → `returned_empty`. Two terminal end-of-shipment values: `delivered` (laden container gated out to the consignee at the destination port) and `returned_empty` (the empty box was returned to the depot AFTER delivery — the true end of shipment). `returned_empty` outranks `delivered`; a box that has been returned reads `returned_empty` even though it was `delivered` earlier.
      - `new_status` 'pre_departure' | 'in_transit' | 'at_transshipment' | 'at_anchor' | 'at_berth' | 'arriving' | 'discharged' | 'customs_hold' | 'available' | 'delivered' | 'returned_empty' | 'cancelled' | 'unknown', required: Derived container status (from `GET /v1/containers/{id}`). Ocean lifecycle order — `discharged` → `available` → `delivered` → `returned_empty`. Two terminal end-of-shipment values: `delivered` (laden container gated out to the consignee at the destination port) and `returned_empty` (the empty box was returned to the depot AFTER delivery — the true end of shipment). `returned_empty` outranks `delivered`; a box that has been returned reads `returned_empty` even though it was `delivered` earlier.
      - `eta` string, date-time, nullable: Current ETA at the moment the event fired. UTC.
      - `demurrage_days_overdue` integer, nullable
      - `demurrage_accrued_usd` number, nullable
    - WebhookEtaChangedData: `data` for eta_changed: the carrier moved the ETA by 24 hours or more. Fires at most once per box per day.
      - `container_id` string, uuid, required: Our internal shipment UUID. Not a shipping reference; useful only if you store our ids.
      - `identifier` string, nullable: The reference the shipment is tracked by: a container number, a bill of lading or a booking number, whichever it was added with.
      - `identifier_type` 'container_id' | 'bill_of_lading' | 'booking' | 'null', nullable: What kind of reference `identifier` is. Null when unknown (shipments recorded before the type was stored). Additive field, added 2026-08-19; absent on deliveries produced by older builds.
      - `old_eta` string, date-time, nullable
      - `new_eta` string, date-time, nullable, required
      - `delta_hours` number: Signed shift in hours; positive means later.
    - WebhookScheduleDisruptionData: `data` for schedule_disruption: the matched sailing slipped materially or did not depart. Fired once per distinct disruption per box.
      - `container_id` string, uuid, required: Our internal shipment UUID. Not a shipping reference; useful only if you store our ids.
      - `identifier` string, nullable: The reference the shipment is tracked by. Additive, added 2026-08-19.
      - `identifier_type` 'container_id' | 'bill_of_lading' | 'booking' | 'null', nullable: What kind of reference `identifier` is. Null when unknown (shipments recorded before the type was stored). Additive field, added 2026-08-19; absent on deliveries produced by older builds.
      - `kind` string, required: slipped or not_departed.
      - `dedup_key` string
      - `headline` string, required: One human-readable sentence for the disruption.
      - `delay_hours` number, nullable
    - WebhookMisroutedData: `data` for container_misrouted: a laden box was discharged at a port that is neither its destination nor a transshipment on its route.
      - `container_id` string, uuid, required: Our internal shipment UUID. Not a shipping reference; useful only if you store our ids.
      - `identifier` string, nullable: The reference the shipment is tracked by: a container number, a bill of lading or a booking number, whichever it was added with.
      - `identifier_type` 'container_id' | 'bill_of_lading' | 'booking' | 'null', nullable: What kind of reference `identifier` is. Null when unknown (shipments recorded before the type was stored). Additive field, added 2026-08-19; absent on deliveries produced by older builds.
      - `discharge_port` string, nullable: UN/LOCODE of the actual discharge.
      - `expected_port` string, nullable: UN/LOCODE of the expected destination.
    - WebhookApiChangeData: `data` for api_change_announced: an API change announced ahead of its effective date. The fields mirror the public changelog entry.
      - `notice_days` integer, required: Days between this announcement and the effective date.
    - object: ping: { message }
      - `message` string

## Acknowledgement `2XX`

Acknowledged. Any 2xx stops retries.

---

[API](https://skmtc.dev/trackingmcp/apis/trackingmcp-rest-api.md) · [All operations](https://skmtc.dev/trackingmcp/apis/trackingmcp-rest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/trackingmcp/apis/trackingmcp-rest-api/revisions/6bb8d8172ceb?raw)
