Track a List of Containers
This tutorial guides you through the process of tracking a list of shipments using the Visiwise API. You can use a container number, a bill of lading, or a booking number to start tracking. By the end of this guide, you will be able to submit a shipment import and retrieve consolidated tracking data from multiple sources, including carriers, AIS, terminals, and railways.
Here are the steps you will follow:
- Get your Visiwise API Key.
- Authenticate your API requests.
- Prepare a list of containers & shipments to track.
- Submit your list to create a shipment import.
- Check the status of the import.
- Retrieve the detailed tracking information for your shipments.
Step 1: Get Your Visiwise API Key
To begin, you need to get your Visiwise API Key from your account dashboard by following the instructions in the Authentication section.
Step 2: Authenticate Your API Requests
The Visiwise API uses token-based authentication. To authenticate your requests, you must include your API Key in the Authorization header as a Bearer token.
Here is an example of an authenticated request using cURL:
- cURL
curl -X GET "https://www.visiwise.co/api/v1/shipments/" \
-H "Authorization: Bearer YOUR_VISIWISE_API_KEY"
Understanding Tracking Identifiers
Before you submit a request, it's helpful to understand the different ways you can identify a shipment. You can use a container number, bill_of_lading number, or booking number.
- A Container number is a unique identifier physically marked on the container itself.
- A Bill of Lading or Booking number is a document number issued by a carrier. A single bill of lading or booking can include multiple containers.
Tracking by container number is easy and direct, but it's important to know that containers are reused. A single container number could have multiple past journeys. For example, a container might complete a journey from Shanghai to New York, and a few days later, be assigned to a new journey from New York to Hamburg. If you track only by its number, you might see data from a previous trip.
To ensure you are tracking the correct, current journey, we recommend using the bill of lading number or booking number whenever possible. This links the container to a specific voyage.
Step 3: Prepare Your Tracking Data
To start tracking, you need to create a list of objects. Each object represents a single Shipment Request and tells Visiwise what to track.
Here are the fields for each shipment request object:
| Field Name | Required | Type | Example | Description |
|---|---|---|---|---|
reference | Yes | String | "order-984572" | Your unique internal identifier for this shipment. You can use this reference later to retrieve tracking information. |
tracking_number | Yes | String | "DFSU7162007" | The number you want to track. |
tracking_type | Yes | String | "container" | The type of number provided. Must be one of container, bill_of_lading, or booking. |
carrier_scac | Yes | String | "AUTO" | The SCAC code for the shipping line. If tracking_type is container, you can set this to "AUTO" to let Visiwise detect the carrier automatically. |
name | No | String | "Machine Parts" | A friendly name for this shipment. If a shipment with the same reference already exists, this will update its name. |
Let's prepare a sample list in Python with 5 containers and 3 bills of lading.
- Python
shipments_to_track = [
# Tracking via Container Number (Auto-detecting carrier)
{
"reference": "ref-C001",
"tracking_number": "MRKU4398344",
"tracking_type": "container",
"carrier_scac": "AUTO",
"name": "Electronics Shipment"
},
# Tracking via Container Number (Specifying carrier)
{
"reference": "ref-C002",
"tracking_number": "DFSU7162007",
"tracking_type": "container",
"carrier_scac": "MSCU",
"name": "Auto Parts"
},
{
"reference": "ref-C003",
"tracking_number": "TTNU8871655",
"tracking_type": "container",
"carrier_scac": "ONEY",
"name": "Textiles"
},
{
"reference": "ref-C004",
"tracking_number": "MAGU5231120",
"tracking_type": "container",
"carrier_scac": "OOLU",
"name": "Frozen Goods"
},
{
"reference": "ref-C005",
"tracking_number": "SMCU1188845",
"tracking_type": "container",
"carrier_scac": "SMLM",
"name": "Furniture"
},
# Tracking via Bill of Lading
{
"reference": "ref-B001",
"tracking_number": "MEDUOO753422",
"tracking_type": "bill_of_lading",
"carrier_scac": "MSCU",
"name": "Industrial Machinery"
},
{
"reference": "ref-B002",
"tracking_number": "258496299",
"tracking_type": "bill_of_lading",
"carrier_scac": "MAEU",
"name": "Pharmaceuticals"
},
{
"reference": "ref-B003",
"tracking_number": "NJEX5H314200",
"tracking_type": "bill_of_lading",
"carrier_scac": "SMLM",
"name": "Retail Apparel"
}
]
Step 4: Start a Shipment Import
Now that you have your list, you can send it to Visiwise. You do this by making a POST request to the /v1/shipments/imports endpoint. This creates a job that will process all your shipment requests.
The API will respond immediately with a ShipmentRequestBatch object, which includes a unique id. You will use this id in the next step to check the status of your import.
- Python
- cURL
import requests
import json
BASE_URL = "https://www.visiwise.co"
API_KEY = "YOUR_VISIWISE_API_KEY"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
url = f"{BASE_URL}/api/v1/shipments/imports"
response = requests.post(url, headers=headers, data=json.dumps(shipments_to_track, indent=2))
if response.status_code == 202:
shipment_request_batch = response.json()
batch_id = shipment_request_batch["id"]
print(f"Successfully created shipment request batch with ID: {batch_id}")
print(json.dumps(shipment_request_batch, indent=2))
else:
print(f"Error: {response.status_code}")
print(response.text)
curl -X POST "https://www.visiwise.co/api/v1/shipments/imports" \
-H "Authorization: Bearer YOUR_VISIWISE_API_KEY" \
-H "Content-Type: application/json" \
-d '[
{
"reference": "ref-C001",
"tracking_number": "MRKU4398344",
"tracking_type": "container",
"carrier_scac": "AUTO",
"name": "Electronics Shipment"
},
{
"reference": "ref-B001",
"tracking_number": "MEDUOO753422",
"tracking_type": "bill_of_lading",
"carrier_scac": "MSCU",
"name": "Industrial Machinery"
}
]'
Sample Response
The API will return a batch object with a status of processing.
{
"id": "71fb1be9-c191-4372-b881-d111ec65d93d",
"status": "processing",
"created_at": "2025-09-15T14:28:10.531Z",
"results": [
{
"id": "422b3486-7250-4984-afd2-cde9bea2e367",
"reference": "ref-C002",
"tracking_type": "container",
"tracking_number": "DFSU7162007",
"carrier_scac": "MSCU",
"creation_status": "created",
"tracking_status": "processing",
"shipment_id": "17a56f91-88b0-48a2-bbee-7e07e3a0c0da",
"name": "Auto Parts",
...
},
...
]
}
Step 5: Check the Import Status
Because tracking can take some time, the process is asynchronous. You need to periodically check the status of the batch until it changes from processing to completed. You can do this by making a GET request to /v1/shipments/imports/{batch_id}.
This script checks the status every 15 seconds until the batch is complete.
- Python
import time
# Assume 'batch_id' is from the previous step
url_status = f"{BASE_URL}/api/v1/shipments/imports/{batch_id}"
while True:
response = requests.get(url_status, headers=headers)
shipment_request_batch_result = response.json()
status = shipment_request_batch_result.get("status")
print(f"Current batch status: {status} ({shipment_request_batch_result.get('completed_requests')}/{shipment_request_batch_result.get('total_requests')} completed)")
if status != "processing":
print("Batch processing finished.")
print(json.dumps(shipment_request_batch_result, indent=2))
break
time.sleep(15)
Sample Response
Once all requests are processed, the status will update to completed.
{
"id": "71fb1be9-c191-4372-b881-d111ec65d93d",
"status": "completed",
"created_at": "2025-09-15T14:28:10.531Z",
"results": [
{
"id": "422b3486-7250-4984-afd2-cde9bea2e367",
"reference": "ref-C002",
"tracking_type": "container",
"tracking_number": "DFSU7162007",
"carrier_scac": "MSCU",
"creation_status": "created",
"tracking_status": "succeeded",
"shipment_id": "17a56f91-88b0-48a2-bbee-7e07e3a0c0da",
"name": "Auto Parts",
...
},
...
]
}
Step 6: Retrieve Shipment Details
After the batch status is completed, you can retrieve the detailed tracking information for all shipments created in that batch. To do this, you make a GET request to the /v1/shipments/ endpoint and filter the results using the batch_id as a query parameter.
- Python
- cURL
# Assume 'batch_id' is from the previous steps
url = f"{BASE_URL}/api/v1/shipments/"
params = {
"batch_id": batch_id
}
response = requests.get(url, headers=headers, params=params)
shipments = response.json().get("data")
print(f"Retrieved {len(shipments)} shipments for batch {batch_id}:")
print(json.dumps(shipments, indent=2))
Replace BATCH_ID with your batch ID to filter the shipments.
curl -X GET "https://www.visiwise.co/api/v1/shipments/?batch_id=BATCH_ID" \
-H "Authorization: Bearer YOUR_VISIWISE_API_KEY"
Sample Response
The response will be a paginated list of Shipment objects, each containing comprehensive tracking data from all available sources.
{
"data": [
{
"id": "17a56f91-88b0-48a2-bbee-7e07e3a0c0da",
"reference": "ref-C002",
"tracking_number": "DFSU7162007",
"tracking_type": "container",
"carrier_scac": "MSCU",
"last_process_status": "track_succeeded",
"last_process_failure_reason": null,
"data_status": "success",
"container_stage": null,
"custom_fields": {},
"tracking": {
"tracking_freshness": "ok",
"pre": {
...
},
"pol": {
...
},
"pod": {
...
},
"pde": {
...
},
"containers_uri": "/api/v1/shipment/17a56f91-88b0-48a2-bbee-7e07e3a0c0da/containers",
...
}
},
...
],
"pagination": {
...
}
}
Final Example Code
- Python
shipments_to_track = [
# Tracking via Container Number (Auto-detecting carrier)
{
"reference": "ref-C001",
"tracking_number": "MRKU4398344",
"tracking_type": "container",
"carrier_scac": "AUTO",
"name": "Electronics Shipment"
},
# Tracking via Container Number (Specifying carrier)
{
"reference": "ref-C002",
"tracking_number": "DFSU7162007",
"tracking_type": "container",
"carrier_scac": "MSCU",
"name": "Auto Parts"
},
{
"reference": "ref-C003",
"tracking_number": "TTNU8871655",
"tracking_type": "container",
"carrier_scac": "ONEY",
"name": "Textiles"
},
{
"reference": "ref-C004",
"tracking_number": "MAGU5231120",
"tracking_type": "container",
"carrier_scac": "OOLU",
"name": "Frozen Goods"
},
{
"reference": "ref-C005",
"tracking_number": "SMCU1188845",
"tracking_type": "container",
"carrier_scac": "SMLM",
"name": "Furniture"
},
# Tracking via Bill of Lading
{
"reference": "ref-B001",
"tracking_number": "MEDUOO753422",
"tracking_type": "bill_of_lading",
"carrier_scac": "MSCU",
"name": "Industrial Machinery"
},
{
"reference": "ref-B002",
"tracking_number": "258496299",
"tracking_type": "bill_of_lading",
"carrier_scac": "MAEU",
"name": "Pharmaceuticals"
},
{
"reference": "ref-B003",
"tracking_number": "NJEX5H314200",
"tracking_type": "bill_of_lading",
"carrier_scac": "SMLM",
"name": "Retail Apparel"
}
]
import requests
import json
BASE_URL = "https://www.visiwise.co"
API_KEY = "YOUR_VISIWISE_API_KEY"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
url = f"{BASE_URL}/api/v1/shipments/imports"
response = requests.post(url, headers=headers, data=json.dumps(shipments_to_track, indent=2))
if response.status_code == 202:
shipment_request_batch = response.json()
batch_id = shipment_request_batch["id"]
print(f"Successfully created shipment request batch with ID: {batch_id}")
print(json.dumps(shipment_request_batch, indent=2))
else:
print(f"Error: {response.status_code}")
print(response.text)
import time
# Assume 'batch_id' is from the previous step
url_status = f"{BASE_URL}/api/v1/shipments/imports/{batch_id}"
while True:
response = requests.get(url_status, headers=headers)
shipment_request_batch_result = response.json()
status = shipment_request_batch_result.get("status")
print(f"Current batch status: {status} ({shipment_request_batch_result.get('completed_requests')}/{shipment_request_batch_result.get('total_requests')} completed)")
if status != "processing":
print("Batch processing finished.")
print(json.dumps(shipment_request_batch_result, indent=2))
break
time.sleep(15)
# Assume 'batch_id' is from the previous steps
url = f"{BASE_URL}/api/v1/shipments/"
params = {
"batch_id": batch_id
}
response = requests.get(url, headers=headers, params=params)
shipments = response.json().get("data")
print(f"Retrieved {len(shipments)} shipments for batch {batch_id}:")
print(json.dumps(shipments, indent=2))
Wrap-up
Congratulations! You have successfully submitted a shipment import for tracking and retrieved their detailed visibility data. You can now integrate this workflow into your applications to automate shipment tracking at scale.