Look up by identifier
Resolve a container number, bill of lading or booking straight to its record, without holding the UUID. Handy when your own system keys on the carrier reference. One thing to know before you loop over it: an identifier you are not tracking yet is registered on the spot, which consumes a shipment slot exactly as an add would, and the call answers 202 with TRACKING_IN_PROGRESS while the carrier is asked.
Path parameters
The container number, bill of lading or booking you tracked.
Response schema
47 fields
Derived from the example response, nested as the JSON is.
The response contract this build answers, as a date. Pin it in your client and nothing in the shape below moves under you.
Whether the request succeeded.
data
The payload. Everything an endpoint returns sits under this key.
Stable identifier for the record. On the tracking endpoints this is the container UUID, except on a portfolio summary row, where it is the container number.
The container number, or null when the record was tracked by a bill of lading or booking that has not yet resolved to a box.
The bill of lading, or null when the record was not tracked by one.
The container number, bill of lading or booking this record tracks.
What the identifier is. The keyed surface uses container_id, bill_of_lading or booking; the public tracker returns booking_number for the third.
The booking reference, or null when the record was not tracked by one.
Equipment size, for example 40HC. Null when the carrier did not state it.
Equipment family as the carrier names it. Null when unstated.
The type half of the ISO 6346 code (G1 for a general-purpose box, R1 for a reefer). Null when unstated.
The boxes a bill of lading or booking resolves to, each with its own timeline. Null on a plain container lookup.
Current normalised status of the shipment. Ocean lifecycle order: discharged, available, delivered, returned_empty. Two values end a shipment, delivered and returned_empty, and returned_empty outranks delivered.
Carrier name, falling back to the SCAC when we hold no name.
Name of the carrying vessel, or null when the carrier named none.
IMO number of the carrying vessel, or null when unknown.
vessel_position
Live AIS position of the carrying vessel. Null when we hold no IMO or no fix yet.
Latitude.
Longitude.
Origin port name, falling back to its UN/LOCODE.
Destination port name, falling back to its UN/LOCODE.
Arrival time (ISO 8601). Null when the carrier publishes none and we cannot predict one.
How often this lane arrives on time, as a percentage. Null on a lane too thin to score.
The more recent of the carrier check and the AIS fix: when we last learned anything about this shipment.
Which of the two produced last_updated_at: carrier_poll or ais_vessel_position. Null when neither has happened yet.
When we last asked the carrier (ISO 8601).
When the vessel was last actually observed by AIS, or null when we hold no fix.
field_provenance
Per-field account of WHY a declared field is empty, keyed by field name. This is the difference between "the carrier does not publish it", "your contract terms would unlock it" and "it does not apply to this shipment".
last_updated_at
The more recent of the carrier check and the AIS fix: when we last learned anything about this shipment.
Why the field stands where it does: resolved, contract_required, not_published, not_applicable or awaiting_carrier.
What would change the state: supply_terms, wait, or do_not_expect when nothing will.
Where the answer on this call came from: direct_carrier or warm_db.
On a card, whether the slot partners agree with each other. On a prediction, how much to trust the shifted arrival.
The reasoning behind the state, in one sentence, so a support answer does not need our source.
Days of free time left, or null when no terms are on file.
Reserved for a written summary of the shipment. Currently always null.
Milestone timeline, oldest to newest.
events[]
Event code, for example DEPA or LOAD.
DCSA classifier: ACT for actual, EST for estimated, PLN for planned.
True when the event happened. False means planned or estimated.
The event in plain words. A non-actual event is tagged "(planned)".
Event timestamp (ISO 8601).
The port wall-clock for the same moment, naive and with no offset, exactly as a terminal prints it. Null when we could not place the port, and a null here means we do not know, never assume UTC.
Minutes to add to the UTC instant to reach the local wall-clock. Null with the local time.
IANA zone of the port, which survives a DST change in a way a bare offset cannot. Null when the port could not be resolved.
UN/LOCODE for the event, or null when the carrier gave no place.
Errors
A failure carries { "ok": false, "error": { "code", "message", "severity" } }. Branch on the code, and log the message.
Not a failure and not a not-found. The identifier is registered and the carrier has not answered yet. The body carries retry_after_seconds. Poll again rather than adding the box a second time. Note that ok is false on a 202 here, so branch on the status, not on ok alone.
The key is missing, malformed or revoked.
No line recognises this reference. Check the check digit before retrying: a wrong one keeps failing.
We could not read the record. Retry.
curl 'https://api.trackingmcp.com/v1/containers/lookup/MEDU1234562' \
-H "Authorization: Bearer tmcp_YOUR_API_KEY"const res = await fetch("https://api.trackingmcp.com/v1/containers/lookup/MEDU1234562", {
headers: {
"Authorization": "Bearer tmcp_YOUR_API_KEY"
}
});
const data = await res.json();import requests
res = requests.get(
"https://api.trackingmcp.com/v1/containers/lookup/MEDU1234562",
headers={"Authorization": "Bearer tmcp_YOUR_API_KEY"},
)
data = res.json() {
"api_version": "2026-08-04",
"ok": true,
"data": {
"id": "8f1c2d4e-6a3b-4f52-9c70-11ab22cd33ef",
"container_number": "ONEU1234567",
"bl_number": null,
"identifier": "ONEU1234567",
"identifier_type": "container_id",
"booking_number": null,
"container_size": "40HC",
"equipment_type": "High Cube Dry",
"iso_type_code": "45G1",
"child_containers": null,
"status": "discharged",
"carrier": "Maersk",
"vessel_name": "MAERSK NORDDAL",
"vessel_imo": "9894674",
"vessel_position": {
"lat": 21.37788,
"lng": 91.643204
},
"origin_name": "XIAMEN",
"destination_name": "CHITTAGONG",
"eta": "2026-08-14T07:24:00+00:00",
"eta_confidence_pct": 97,
"last_updated_at": "2026-08-16T11:20:18+00:00",
"last_updated_source": "ais_position",
"last_polled_at": "2026-08-16T03:50:21.692+00:00",
"last_ais_fix_at": "2026-08-16T11:20:18+00:00",
"field_provenance": {
"last_updated_at": {
"state": "resolved",
"action": "none",
"source": "ais_vessel_position",
"confidence": "exact",
"evidence": "The vessel carrying this shipment was observed at a position at 2026-08-16T11:20:18+00:00, more recently than our last carrier check at 2026-08-16T03:50:21.692+00:00. A position fix locates the ship; it does not report container milestones, so the carrier is still polled on its own cadence."
}
},
"demurrage_free_days_left": null,
"ai_narrative": null,
"events": [
{
"type": "GTOT",
"classifier": "ACT",
"is_actual": true,
"label": "Gate out",
"timestamp": "2026-07-25T04:05:00+00:00",
"event_local_datetime": "2026-07-25T12:05:00",
"utc_offset_minutes": 480,
"event_timezone": "Asia/Shanghai",
"location": "CNXMN"
},
{
"type": "GTIN",
"classifier": "ACT",
"is_actual": true,
"label": "Gate in",
"timestamp": "2026-07-25T11:05:00+00:00",
"event_local_datetime": "2026-07-25T19:05:00",
"utc_offset_minutes": 480,
"event_timezone": "Asia/Shanghai",
"location": "CNXMN"
}
]
}
}