Vizion
Migrate from Vizion to TimeToCargo API v2: authentication, requests and response handling
This guide covers migration from Vizion Container Tracking API to TimeToCargo API v2. A Vizion reference tracks a reference number, while an update contains data from one refresh. Preserve record ID mappings and the update history you need.
See the migration workflow for importing references and setting up notifications. Full TimeToCargo schemas are in the API reference.
Authentication
Vizion uses the X-API-Key header. The Vizion base URL is https://prod.vizionapi.com.
To switch to TimeToCargo:
- Create a key in your TimeToCargo account.
- Change the base URL to
https://tracking.timetocargo.com/v2. For example, the full tracking endpoint ishttps://tracking.timetocargo.com/v2/tracking. - Send the new key in the
api_keyquery parameter of every request, including batch tasks and webhook management. Keys and tokens from the former provider cannot be reused.
See authentication for key usage and request limits.
Tracking records and identifiers
| Vizion | TimeToCargo | Required change |
|---|---|---|
reference | shipment | Map the reference ID to the new tracking ID. Use the new ID to manage the record. |
parent reference / child references | shipment + containers[] | For a bill of lading or booking, process containers within one result. Retain source parent-child ID relationships locally. |
update / milestone | Tracking snapshot / containers[].events[] | Read current data from the tracking record and shipment events from containers[].events[]. Store incoming webhooks to retain update history. |
Operation mapping
| Vizion | TimeToCargo | Required change |
|---|---|---|
POST /references | POST /v2/tracking/batch → GET /v2/tracking/batch | Submit references, retrieve the task result, and save the permanent ID from data.results[].data.tracking_metadata.id. |
GET /references | GET /v2/shipments?status=ACTIVE | Fetch active records using page and limit. Query the archive separately with status=ARCHIVED. |
GET /references/{referenceId} | GET /v2/shipments | Fetch list pages and find the record using the new ID from your mapping table. There is no individual GET by ID. |
GET /references/{referenceId}/updates | /v2/webhooks + snapshot storage | Export past Vizion updates. For future history, configure webhooks and store each received notification in your system. |
GET /references/last-known-positions | GET /v2/shipments?need_route=true | Read route_info.current_position from the stored tracking record. Retain Vizion position history separately. |
GET /carriers | GET /v2/companies | Map the Vizion carrier code to a SCAC in the new directory. Check support for the reference type in cn, bl and bk. |
POST/DELETE /tags, tag association | PATCH /v2/shipments/{id} (partial) | Move one label of up to 40 characters into note. Maintain tag collections and their tracking associations in your own system. |
DELETE /references/{referenceId} | DELETE /v2/shipments | Send the new IDs in the shipmentIds array. Check archiving and deletion rules in the lifecycle guide. |
Request parameters
| Vizion | TimeToCargo | Required change |
|---|---|---|
container_id / bill_of_lading / booking_number | tracked_items[].track_number.value + type | Choose the primary reference and put it in track_number.value. Set type to container, bl or bk for a container, bill of lading or booking. |
carrier_code / scac | tracked_items[].company | Find the matching SCAC through GET /v2/companies. Verify an internal Vizion code before reusing it. |
callback_url | POST /v2/webhooks | Remove callback_url from the tracking request. Create a webhook separately with POST /v2/webhooks using the webhook guide. |
tags / reference metadata | note + your own store | Once you have the permanent ID, save one label as note through PATCH /v2/shipments/{id}. Keep remaining metadata locally. |
pagination / filters | page / limit / status | Use page, limit and the subscription status filter. Apply other selection criteria locally after fetching pages. |
Response fields
Select a record from data.data[] in the GET /v2/shipments response. Paths starting with tracked_item are relative to that record. Containers are in tracked_item.data.data.containers[], with events in each container's events[]. In GET /v2/tracking, shipment data is directly under data.
| Vizion | TimeToCargo | Response handling |
|---|---|---|
reference.id / id | data.data[].id | Save the new data.data[].id alongside the source Vizion ID. These IDs are issued independently and do not match. |
active | data.data[].status | Replace the boolean active check with comparisons against ACTIVE and ARCHIVED. |
last_update_status | tracked_item.data.success / status | Check nested success and status for tracking data availability. Check webhook delivery failures separately in the notification log. |
update.payload.milestones[] | tracked_item.data.data.containers[].events[] | Read events from containers[].events[]. Replace timestamp with date, description with status, and invert planned to obtain actual. |
geolocation.latitude / longitude | route_info.current_position | Read coordinates from current_position: latitude first, longitude second. Handle a possible null. |
timestamp / mode_details | route_info.last_updated / partial | last_updated refers to the current position update and may be null. Its source can differ from Vizion; there is no complete mode_details object. |
Response examples
Each pair labels the former-provider and TimeToCargo responses. Expand the longer JSON examples when you need them; the mapping tables remain visible. These are shortened examples with illustrative data. The path above each JSON block identifies the part shown. Paths in the following table start from that part.
Tracking record, reference and subscription status
Vizion — GET /references/{referenceId}
Shortened response.
{
"id": "33333333-3333-4333-8333-333333333333",
"container_id": "MSCU1234567",
"bill_of_lading": null,
"carrier_code": "MSCU",
"active": true,
"last_update_status": "data_received",
"latest_update_id": "55555555-5555-4555-8555-555555555555",
"parent_reference_id": null
}TimeToCargo — GET /v2/shipments
Fragment: data.data[0].
{
"id": "11111111-1111-4111-8111-111111111111",
"status": "ACTIVE",
"note": "Order 123",
"track_number": "MSCU1234567",
"tracked_item": {
"track_number": "MSCU1234567",
"track_number_type": "container",
"data": {
"success": true,
"status": "OK",
"data": {
"summary": {
"company": {
"name": "MSC",
"scacs": ["MEDU", "MSCU"]
}
},
"shipment_status": "IN_TRANSIT",
"containers": [
{
"number": "MSCU1234567",
"type": "40' High Cube Dry"
}
]
}
}
}
}How to map
| Vizion | TimeToCargo | Required change |
|---|---|---|
id = "33333333-3333-4333-8333-333333333333" | id = "11111111-1111-4111-8111-111111111111" | Map the source reference ID to the new id in your database. Do not pass a Vizion ID to tracking management operations. |
container_id = "MSCU1234567" | tracked_item.track_number = "MSCU1234567" | Here, container_id contains the container number. Read the same number from tracked_item.track_number. |
active = true | status = "ACTIVE" | Replace active=true checks with status: "ACTIVE". This is the subscription status, not shipment progress. |
last_update_status = "data_received" | tracked_item.data.status = "OK" | The example's data_received corresponds to nested status: "OK". Check shipment progress separately in shipment_status. |
carrier_code = "MSCU" | tracked_item.data.data.summary.company.scacs = ["MEDU","MSCU"] | Look for MSCU in the scacs array. For other records, verify the Vizion code against the new carrier directory first. |
latest_update_id = "55555555-5555-4555-8555-555555555555" | No direct equivalent | The current response has no separate update ID. Retain the old latest_update_id with the update archive if needed. |
Update: events and planned timestamps
Vizion — GET /references/{referenceId}/updates
Fragment: [0].
{
"id": "55555555-5555-4555-8555-555555555555",
"reference_id": "33333333-3333-4333-8333-333333333333",
"status": "data_received",
"payload": {
"container_id": "MSCU1234567",
"container_iso": "45G1",
"carrier_scac": "MSCU",
"milestones": [
{
"description": "Loaded",
"timestamp": "2026-10-01T04:00:00Z",
"planned": false,
"shipment_location": {
"type_code": "POL"
},
"location": {
"name": "Singapore",
"unlocode": "SGSIN",
"geolocation": {
"latitude": 1.25,
"longitude": 103.75
}
},
"vessel": "EXAMPLE VESSEL",
"voyage": "126E"
},
{
"description": "Vessel arrival",
"timestamp": "2026-10-12T06:00:00Z",
"planned": true,
"shipment_location": {
"type_code": "POD"
},
"location": {
"name": "Rotterdam",
"unlocode": "NLRTM",
"geolocation": {
"latitude": 51.95,
"longitude": 4.14
}
},
"vessel": "EXAMPLE VESSEL",
"voyage": "126E"
}
]
}
}TimeToCargo — GET /v2/shipments
Fragment: data.data[0].tracked_item.data.data.
{
"locations": [
{
"id": 0,
"name": "Singapore",
"country": "Singapore",
"lat": 1.25,
"lng": 103.75
},
{
"id": 1,
"name": "Rotterdam",
"country": "Netherlands",
"lat": 51.95,
"lng": 4.14
}
],
"containers": [
{
"number": "MSCU1234567",
"type": "40' High Cube Dry",
"events": [
{
"location": 1,
"status": "Vessel arrival",
"status_code": "VAD",
"date": "2026-10-12T08:00:00",
"actual": false,
"vessel": "EXAMPLE VESSEL",
"voyage": "126E"
},
{
"location": 0,
"status": "Loaded",
"status_code": "CLL",
"date": "2026-10-01T12:00:00",
"actual": true,
"vessel": "EXAMPLE VESSEL",
"voyage": "126E"
}
]
}
]
}How to map
| Vizion | TimeToCargo | Required change |
|---|---|---|
payload.container_id = "MSCU1234567" | containers[0].number = "MSCU1234567" | Find the container by containers[].number and process that container's events. |
payload.milestones[0].description = "Loaded" | containers[0].events[1].status = "Loaded" | The text Loaded is in status. Use status_code: "CLL" to handle origin-port loading in code. |
payload.milestones[0].planned = false | containers[0].events[1].actual = true | For an actual event, replace planned=false with actual=true. |
payload.milestones[1].planned = true | containers[0].events[0].actual = false | For a planned event, replace planned=true with actual=false. |
payload.milestones[0].location | locations[0] | Look up the location in locations using event.location. Do not expect a nested object inside the event. |
payload.milestones[0].timestamp = "2026-10-01T04:00:00Z" | containers[0].events[1].date = "2026-10-01T12:00:00" | In this example, 04:00 UTC is 12:00 in Singapore. Account for the location's time zone when comparing dates rather than simply removing Z. |
payload.container_iso = "45G1" | No direct equivalent | There is no separate equipment ISO code. Retain 45G1 locally if your system uses that classification. |
The source shows one update from the array response. The target shows current stored tracking data, not a copy of all update history.
Latest position and vessel context
Vizion — GET /references/last-known-positions
Fragment: [0].
{
"reference_id": "33333333-3333-4333-8333-333333333333",
"container_id": "MSCU1234567",
"timestamp": "2026-10-03T08:30:00Z",
"mode": "Vessel",
"mode_details": {
"vessel": "EXAMPLE VESSEL",
"vessel_imo": "9000003"
},
"geolocation": {
"latitude": 1.25,
"longitude": 103.75
}
}TimeToCargo — GET /v2/shipments?need_route=true
Fragment: data.data[0].
{
"id": "11111111-1111-4111-8111-111111111111",
"tracked_item": {
"data": {
"data": {
"route_info": {
"current_position": [1.25, 103.75],
"last_updated": "2026-10-03T09:00:00"
}
}
}
}
}How to map
| Vizion | TimeToCargo | Required change |
|---|---|---|
reference_id = "33333333-3333-4333-8333-333333333333" | id = "11111111-1111-4111-8111-111111111111" | Resolve the new ID through your saved reference_id mapping. The source Vizion ID will not appear in the new response. |
geolocation | tracked_item.data.data.route_info.current_position = [1.25,103.75] | Read the point as a [latitude, longitude] array, for example [1.25, 103.75]. |
timestamp = "2026-10-03T08:30:00Z" | tracked_item.data.data.route_info.last_updated = "2026-10-03T09:00:00" | last_updated refers to the current position in the new response. That position may come from another source, so retain the original Vizion timestamp separately. |
mode_details.vessel_imo = "9000003" | No direct equivalent | The vessel IMO is not returned as a separate field. Keep it locally if you need links to external vessel data. |
Data to retain separately
Export required Vizion updates before switching off the service. Store incoming webhooks for future history. /v2/shipments returns current tracking data, while /v2/webhook-notifications records notification delivery. Use the list to retrieve an existing record rather than initiating /v2/tracking again.
Last updated on