You need to track a general cargo ship reliably, get a live AIS position with route and ETA, understand recent port calls, and optionally compute its IMO CII rating for ESG reporting. By the end of this guide, you’ll query a specific general cargo vessel, retrieve its latest track and voyage context, pull port-facing signals for operations, and assemble a minimal integration that can ship in production.
What “tracking a general cargo ship” actually involves
General cargo ships operate on diverse routes with frequent port calls. To power an operations dashboard, you typically need:
- Discovery: Search by name, IMO, or MMSI to confirm the target vessel.
- Live context: Current AIS position, course, speed, nav status, and a short history window for state changes.
- Voyage intelligence: Declared route (departure/destination), predicted ETA, and last port visits.
- Operational coordination: Expected arrivals for a port, and congestion/wait-time snapshots.
- ESG and compliance: IMO CII emissions scoring over a reporting period.
vessels-api.com exposes this via a consistent REST surface with 18 endpoints, one API key header, and a single base URL: https://vessels-api.com/api/V1. Every response uses the same JSON envelope: {status, success, message, data}.
Core endpoints for general cargo tracking
The following endpoints cover most production needs for this vessel class:
- GET /vessels/search — identify a vessel by name (fuzzy), IMO, or MMSI, filtered by ship type.
- GET /vessels/track — live AIS position, short history, route, predicted ETA, and last port calls.
- GET /port/expected-arrivals — what’s inbound to a port with ETAs and origin signals.
- GET /vessels/analytics — aggregate voyage stats for performance and ops KPIs.
- GET /vessels/green — IMO CII scoring with emissions estimates.
Authentication is the same across all endpoints: add X-API-Key: YOUR_API_KEY to each request. Timestamps are UTC. Distances are nautical miles (nm). Speeds are in knots. Pagination applies to list endpoints as documented.
Step 1 — Find the general cargo ship
Start by searching for the vessel. If you already have the MMSI or IMO, you can skip straight to tracking. Otherwise, search by a fuzzy name and optionally filter to cargo vessels.
cURL
curl -H "X-API-Key: YOUR_API_KEY" "https://vessels-api.com/api/V1/vessels/track?mmsi=258785000&hours=48"
Key parameters:
- query: vessel name (fuzzy), IMO, or MMSI.
- ship_type: filter results (e.g., General Cargo).
- page, per_page: control pagination (per_page up to 100).
From the response, capture either the IMO or MMSI for subsequent calls. Typical fields include name, flag, vessel_type, and dimensions to confirm you’ve selected the correct ship.
Step 2 — Live tracking, route, and last port calls
Use GET /vessels/track to retrieve the current position, route snapshot, optional ETA prediction, and a limited history window (up to 168 hours).
Official cURL sample
Official JSON sample response
{
"status": 200,
"success": true,
"message": "OK",
"data": {
"vessel": {
"imo": "9122556",
"mmsi": "258785000",
"name": null
},
"current_position": {
"latitude": 53.33708,
"longitude": 7.17993,
"speed_knots": 0,
"course_degrees": 212,
"heading_degrees": null,
"navigational_status": 5,
"timestamp_utc": "2017-01-24T04:07:54+00:00",
"age_minutes": 5150180,
"destination": null,
"eta": null
},
"predicted_eta": null,
"position_history": [],
"route": {
"departure_port": "HERACLIO",
"departure_time": "2026-04-27T21:35:36+00:00",
"destination_port": "HERACLIO",
"eta": null,
"distance_nm": null,
"avg_speed_knots": 17.1
},
"last_port_visits": [
{
"port_id": "156",
"port_name": "EMDEN",
"arrival_time": "2026-07-30T13:00:10+00:00",
"departure_time": null,
"duration_hours": null
},
{
"port_id": "10",
"port_name": "HERACLIO",
"arrival_time": "2026-04-20T12:00:00+00:00",
"departure_time": "2026-04-23T08:00:00+00:00",
"duration_hours": 68
}
],
"weather": null
}
}
What to use in your app:
- data.vessel: identifiers for linking to fleet records.
- current_position: core tracking — latitude/longitude, speed_knots, course_degrees, navigational_status (AIS nav status code), timestamp_utc.
- route: departure/destination, departure_time, eta, avg_speed_knots. Useful for plan vs. actual.
- last_port_visits: recent events for supply chain and port ops features.
Python example: poll, normalize, and cache a general cargo position
import os
import time
import requests
API_KEY = os.getenv("VESSELS_API_KEY", "YOUR_API_KEY")
BASE = "https://vessels-api.com/api/V1"
def track_by_mmsi(mmsi: str, hours: int = 24, include_route: bool = True):
url = f"{BASE}/vessels/track"
params = {"mmsi": mmsi, "hours": hours}
if include_route:
params["include_route"] = "true"
r = requests.get(url, headers={"X-API-Key": API_KEY}, params=params, timeout=20)
r.raise_for_status()
payload = r.json() # {status, success, message, data}
if not payload.get("success"):
raise RuntimeError(payload.get("message"))
d = payload["data"]
pos = d.get("current_position") or {}
route = d.get("route") or {}
return {
"mmsi": d["vessel"].get("mmsi"),
"imo": d["vessel"].get("imo"),
"lat": pos.get("latitude"),
"lon": pos.get("longitude"),
"sog_kn": pos.get("speed_knots"),
"cog_deg": pos.get("course_degrees"),
"nav_status": pos.get("navigational_status"),
"ts_utc": pos.get("timestamp_utc"),
"destination": pos.get("destination") or route.get("destination_port"),
"eta": pos.get("eta") or route.get("eta"),
"departure_port": route.get("departure_port"),
"avg_speed_knots": route.get("avg_speed_knots"),
}
if __name__ == "__main__":
data = track_by_mmsi("258785000", hours=48)
print(data)
Implementation notes:
- Cache by MMSI/IMO for a short TTL (e.g., 30–60 seconds) depending on your UI refresh cadence.
- If include_predicted_eta is set server-side, prefer predicted_eta when current_position.eta is null.
- If you need history, increase hours up to 168; expect larger payloads.
Step 3 — Port-facing signals: expected arrivals
General cargo planning often hinges on inbound calls and ETAs. Use GET /port/expected-arrivals to power port-centric views (terminal prep, yard planning) or to detect if a target vessel is expected.
cURL
The response includes:
- data.port_id, data.port_name: identifiers for display.
- data.expected_arrivals: array with mmsi, imo, name, vessel_type, eta, departure_port.
- data.total: count of expected arrivals.
Join this to a tracked MMSI or IMO to validate whether your general cargo ship is on the slate for that port, and to compare current_position-derived ETAs with published ETAs.
Step 4 — Voyage analytics for operations KPIs
GET /vessels/analytics aggregates metrics like distance sailed, average speed, and port calls over a period. For a general cargo ship, these KPIs support cycle-time analysis, on-time performance, and maintenance scheduling.
cURL
Key output fields:
- statistics.total_distance_nm: total nautical miles traveled.
- statistics.avg_speed_knots and max_speed_knots: speed profile.
- statistics.port_calls_count and total_time_in_port_hours: port-cycle efficiency.
- statistics.ports_visited: useful for lane analysis.
You can also switch type to port or fleet (using mmsi_list) to roll up KPIs across multiple general cargo ships.
Step 5 — ESG and compliance: IMO CII scoring
For general cargo ships included in ESG reporting, the /vessels/green endpoint returns an estimated emissions profile and the IMO CII rating for a given period. Ratings follow MEPC.339(76) with A (best) to E (worst).
cURL
Use the following fields:
- data.cii.score and data.cii.rating: the computed CII.
- data.estimated_emissions.co2_tons: period CO2 estimate.
- data.distance_nm and co2_per_nm: intensity signals for benchmarking similar ships.
Combine CII with analytics to identify operational levers (speed, port time) that influence emissions intensity.
Optional — Discover vessels near your asset
When coordinating pilots or tugs for a general cargo ship, it’s handy to see nearby traffic. Use GET /vessels/nearby with a lat/lon and radius to return traffic in nautical miles, optionally filtered by ship_type to isolate general cargo.
cURL
The response includes each vessel’s distance_nm from your center point and a timestamp_utc for the position freshness. Apply a short TTL cache; avoid polling too frequently unless your UI truly requires it.
Putting it together: a minimal pipeline
Below is a compact approach to tracking one general cargo ship, checking its port arrival, calculating KPIs, and surfacing the CII rating. For production, add caching, retries, circuit breakers, and backoff on 429/500 as needed.
Python example: end-to-end workflow
import os
import requests
API_KEY = os.getenv("VESSELS_API_KEY", "YOUR_API_KEY")
BASE = "https://vessels-api.com/api/V1"
HEADERS = {"X-API-Key": API_KEY}
def track(mmsi: str):
url = f"{BASE}/vessels/track"
params = {"mmsi": mmsi, "hours": 24, "include_route": "true", "include_predicted_eta": "true"}
r = requests.get(url, headers=HEADERS, params=params, timeout=20)
r.raise_for_status()
return r.json()["data"]
def analytics(mmsi: str, period="7d"):
url = f"{BASE}/vessels/analytics"
params = {"type": "vessel", "mmsi": mmsi, "period": period}
r = requests.get(url, headers=HEADERS, params=params, timeout=20)
r.raise_for_status()
return r.json()["data"]["statistics"]
def cii(mmsi: str, period="30d"):
url = f"{BASE}/vessels/green"
params = {"mmsi": mmsi, "period": period}
r = requests.get(url, headers=HEADERS, params=params, timeout=20)
r.raise_for_status()
return r.json()["data"]["cii"]
def expected_arrivals(port_id: str):
url = f"{BASE}/port/expected-arrivals"
params = {"port": port_id}
r = requests.get(url, headers=HEADERS, params=params, timeout=20)
r.raise_for_status()
return r.json()["data"]["expected_arrivals"]
if __name__ == "__main__":
mmsi = "258785000"
td = track(mmsi)
pos = td.get("current_position") or {}
route = td.get("route") or {}
print("Position:", pos.get("latitude"), pos.get("longitude"), pos.get("timestamp_utc"))
print("Route:", route.get("departure_port"), "→", route.get("destination_port"), "ETA:", route.get("eta"))
kpis = analytics(mmsi, period="7d")
print("KMIs (7d):", kpis)
rating = cii(mmsi, period="30d")
print("CII:", rating)
# If we know the destination port code, check expected arrivals
dest = route.get("destination_port")
if dest:
arrivals = expected_arrivals(dest)
found = any(v.get("mmsi") == mmsi for v in arrivals)
print("On expected-arrivals list:", found)
Error handling and production considerations
- Authentication: All endpoints require X-API-Key. A 401 indicates a missing/invalid key.
- Validation: A 400/422 indicates missing/invalid parameters or out-of-range values (e.g., radius or hours beyond max).
- Not found: 404s for vessels/ports that cannot be resolved. For search, widen filters.
- Rate limiting: 429 indicates you should add backoff and caching. Only poll at the cadence your UI needs.
- Units and time: Distances in nautical miles (nm), speed in knots, UTC timestamps. Display in local time zones only on the client.
- Pagination: On list endpoints (search, arrivals), check pagination or counts if building infinite scrolls or summaries.
Why developers ship with vessels-api.com
- One key, one base URL: no OAuth variations or per-endpoint differences.
- Consistent JSON envelope across endpoints simplifies parsing and error flows.
- Global AIS coverage with near real-time refresh supports both dashboard and automation use cases.
- Feature breadth: 18 endpoints spanning vessel search, live tracking, fleet, port intelligence, analytics, and CII scoring.
Beyond individual calls, the uniform response model and shared headers make it straightforward to compose higher-level workflows, like correlating track data with port arrivals and CII in a single screen for a general cargo ship.
Frequently asked questions
How often should I poll /vessels/track for a general cargo vessel?
Match polling to your UI and operational need. Many dashboards update every 30–60 seconds. Cache by MMSI/IMO for the same TTL to reduce load. If you need history, set hours accordingly, but avoid requesting the max window on each refresh.
Should I use IMO or MMSI?
Use whichever identifier is stable in your system. MMSI is easy to query for AIS data; IMO is a persistent vessel identifier. The API accepts either on most vessel-centric endpoints.
What does navigational_status represent?
It’s the AIS nav status code from the transponder (e.g., underway, at anchor). Use it with speed_knots and course_degrees to infer operational state changes (e.g., arrival to anchorage).
How do I get a predicted ETA?
For /vessels/track, include the optional include_predicted_eta flag if you want a server-side predicted_eta field. If current_position.eta is null, predicted_eta can supplement downstream planning.
Can I aggregate stats across multiple general cargo ships?
Yes. Use /vessels/analytics with type=fleet and pass mmsi_list, or use /vessels/fleet (POST) to pull positions and routes for multiple ships in a single call, then aggregate client-side.
Next steps
Build your general cargo ship integration using the live examples above, then expand to fleet analytics and port operations as needed. Start with the reference docs and test endpoints in your environment:
With a single API key and consistent responses across endpoints, you can ship a reliable general cargo tracking feature in hours—not weeks.