You need to track a Ro-Ro vessel end-to-end: locate it quickly, stream its latest AIS position with speed/course, get voyage context (route, last port calls, ETA), and roll that up across a car-carrier fleet and destination ports. By the end of this guide, you’ll query live AIS for a known MMSI, search for a Ro-Ro by name or IMO, batch-track multiple Ro-Ros in one call, and pull port intelligence to keep yard and berth plans in sync.
Why this API fits Ro-Ro tracking workflows
Ro-Ro operations are schedule-sensitive: short port stays, tight yard windows, and variable coastal routing. Vessels API exposes the signals Ro-Ro teams need through a small set of purpose-built endpoints:
- Vessel discovery: GET /vessels/search for fuzzy name, IMO, or MMSI lookups with ship-type filters.
- Live tracking: GET /vessels/track for current AIS position, 24–168h history, route, predicted ETA, and port visits.
- Fleet rollups: POST /vessels/fleet to retrieve positions and routes for many Ro-Ros in a single request.
- Port intelligence: GET /port/expected-arrivals, GET /ports/congestion for planning gate, berth, and yard resources.
- ESG compliance: GET /vessels/green for IMO CII scoring aligned with MEPC.339(76).
Key advantages for engineering teams:
- 18 REST endpoints across vessel tracking, fleet ops, ports, and emissions.
- One API key via X-API-Key. No OAuth flows, no per-endpoint differences.
- Consistent JSON envelope: {status, success, message, data} on every response.
- Global AIS coverage with near real-time refresh, suitable for dashboards and alerting.
- 7-day free trial that scales from a single Ro-Ro to enterprise fleets.
Base URL, authentication, and response envelope
All endpoints live under the same base URL and use the same header:
- Base URL: https://vessels-api.com/api/V1
- Header: X-API-Key: YOUR_API_KEY
- Methods: GET for most resources; POST for /vessels/fleet
Responses follow a consistent envelope. Check status/success before reading data:
{
"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:45+00:00",
"age_minutes": 5117600,
"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": "2026-04-30T09:00:00+00:00",
"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
}
}
Units and conventions you’ll need right away:
- Speed in knots; distances in nautical miles (nm).
- Positions are latitude/longitude in decimal degrees.
- Timestamps are ISO-8601 UTC with offset (e.g., 2026-04-30T09:00:00+00:00).
Live-track a Ro-Ro with current position, route, and port calls
The most direct way to track a Ro-Ro is by MMSI or IMO using GET /vessels/track. You can request up to 168 hours of history, and optionally include route context, predicted ETA, and weather. Below is the official sample focused on the documented MMSI 258785000 over a 48h window.
Official cURL (copy-paste)
curl -H "X-API-Key: YOUR_API_KEY" "https://vessels-api.com/api/V1/vessels/track?mmsi=258785000&hours=48"
Official JSON response
Fields you’ll actually use for Ro-Ro ops
- current_position.latitude/longitude: plot on map or feed to geofencing logic for anchorage/berth detection.
- current_position.speed_knots and course_degrees: gate and berth ETA heuristics when no predicted_eta is present.
- current_position.timestamp_utc and age_minutes: data freshness guard; reject stale AIS to avoid bad alerts.
- route.departure_port, destination_port, eta, avg_speed_knots: voyage context to line up yard resources.
- last_port_visits: derive lane patterns and dwell time by port for schedule reliability metrics.
Python example: parse position and route into an ETA widget
import requests
from datetime import datetime, timezone
API_KEY = "YOUR_API_KEY"
URL = "https://vessels-api.com/api/V1/vessels/track"
params = {
"mmsi": "258785000",
"hours": "48"
}
resp = requests.get(URL, headers={"X-API-Key": API_KEY}, params=params, timeout=15)
resp.raise_for_status()
payload = resp.json()
if not payload.get("success"):
raise RuntimeError(f"API error: {payload.get('message')}")
data = payload["data"]
vessel = data["vessel"]
pos = data["current_position"]
route = data.get("route") or {}
# Guard against stale AIS
age_minutes = pos.get("age_minutes")
fresh = age_minutes is not None and age_minutes <= 60
eta = (route.get("eta") or pos.get("eta"))
eta_dt = None
if eta:
eta_dt = datetime.fromisoformat(eta.replace("Z", "+00:00"))
summary = {
"mmsi": vessel.get("mmsi"),
"imo": vessel.get("imo"),
"lat": pos.get("latitude"),
"lon": pos.get("longitude"),
"speed_knots": pos.get("speed_knots"),
"course_deg": pos.get("course_degrees"),
"fresh": fresh,
"destination_port": route.get("destination_port"),
"eta_utc": eta_dt.isoformat() if eta_dt else None
}
print(summary)
JavaScript example (Node.js/fetch): map marker + freshness check
import fetch from "node-fetch";
const API_KEY = "YOUR_API_KEY";
const url = "https://vessels-api.com/api/V1/vessels/track?mmsi=258785000&hours=48";
const res = await fetch(url, {
headers: { "X-API-Key": API_KEY }
});
const json = await res.json();
if (!json.success) {
throw new Error(json.message || "Request failed");
}
const { vessel, current_position: cp, route } = json.data;
const marker = {
id: vessel.mmsi,
lat: cp.latitude,
lon: cp.longitude,
speed: cp.speed_knots,
course: cp.course_degrees,
fresh: cp.age_minutes !== null && cp.age_minutes <= 60
};
const voyage = {
dest: route?.destination_port || null,
eta: route?.eta || cp.eta || null
};
console.log({ marker, voyage });
Find a Ro-Ro fast by name, IMO, or MMSI
To bootstrap a fleet or when a terminal sends a short name, use GET /vessels/search. Apply filters like ship_type=Ro-Ro to narrow results and feed MMSIs into your tracking pipeline.
Notes:
- Fuzzy name matching helps normalize “ATLANTIC HIGHWAY” vs “ATLANTIC-HWY”.
- Pagination with page and per_page (max 100). Cache recent lookups to lower latency.
- Use returned fields like imo, mmsi, vessel_type, length_m for berth compatibility checks.
Batch-track multiple Ro-Ros with one request
Fleet dashboards and KPI jobs benefit from fewer round-trips. POST /vessels/fleet returns positions, optional routes, and basic rollups in one payload.
cURL (POST) with two identifiers and positions included
Tips for Ro-Ro fleets:
- Mix IMO and MMSI in the same request; the API resolves either.
- Store fleet: {imo,mmsi,name} in your DB and refresh positions on an interval appropriate for your UI (e.g., 2–5 minutes).
- Use the returned fleet.vessels_at_sea vs vessels_in_port to drive yard staffing alerts.
Port-facing signals: arrivals, congestion, and proximity
Two operational questions dominate Ro-Ro port work: what’s arriving next, and how busy is the port. Augment your vessel view with these readouts.
Expected arrivals for a port
GET /port/expected-arrivals gives you vessels inbound to a given UNLOCODE-style port identifier with ETA and origin. Use it to construct port-side arrival boards and plan yard gates.
Fields to consume: expected_arrivals[].{mmsi,imo,name,vessel_type,eta,departure_port}. Filter by vessel_type to isolate Ro-Ro calls.
Congestion snapshot and wait-time statistics
GET /ports/congestion provides a real-time snapshot and historical wait-time stats for a port. Use period=24h|3d|7d to adjust window. Do not fabricate counts—consume them as provided by the API.
Key fields: snapshot.vessels_in_anchorage, snapshot.vessels_at_berth, statistics.avg_wait_time_hours_last_7d, max_wait_time_hours_last_7d, avg_berth_time_hours_last_7d, port_calls_count.
Proximity alerts around your terminal
For geofenced alerts (e.g., “notify when any Ro-Ro enters 20 nm of the pilot station”), GET /vessels/nearby returns all vessels near a coordinate with distance_nm and last position timestamp.
Use distance_nm together with speed_knots to build a conservative “time-to-zone” estimate even before a route ETA is published.
ESG and compliance: CII scoring for Ro-Ro vessels
Automotive OEMs and carriers face growing pressure to report emissions intensity at the vessel level. GET /vessels/green returns distance and estimated CO₂ over a period with an IMO CII score and rating (A–E) for reporting and internal optimization.
Practical usage:
- Compare cii.rating across potential sailings for lane assignment decisions.
- Annotate your vessel cards with cii.rating and co2_per_nm to track efficiency seasonality.
- Persist regulation_reference for audit trails (MEPC.339(76)).
Analytics rollups for schedule reliability
For Ro-Ro reliability metrics, GET /vessels/analytics aggregates voyage stats by vessel, port, or fleet over periods like 7d/30d/90d.
Important fields: statistics.total_distance_nm, avg_speed_knots, max_speed_knots, port_calls_count, total_time_in_port_hours, ports_visited. For schedule adherence, compare total_time_in_port_hours against your berth plan norms.
Implementation details that save time
- Pagination: /vessels/search returns pagination.{current_page, per_page, total, last_page}. Iterate until current_page == last_page.
- Freshness: Always check current_position.age_minutes. If your SLA requires fresh data, hide positions older than your threshold.
- Fallback ETA: Prefer route.eta or predicted_eta. If neither is present, derive a rough ETA using remaining distance (if available) or distance_nm from your port geofence divided by speed_knots, capping min speeds to avoid divide-by-zero.
- Error handling: honor HTTP 400/401/404/422/429/500. For 429, backoff before retrying. Preserve message for operator logs.
- Time zones: All timestamps are UTC. Convert to local port time in your UI using port.timezone from GET /ports or /ports/data.
- Batching: Prefer POST /vessels/fleet over N single /vessels/track calls when refreshing dashboards.
- Caching: Cache /vessels/search and /ports listings for hours. For live tracks, choose a polling cadence that matches your UX needs and avoids unnecessary churn.
End-to-end example: small Ro-Ro dashboard flow
- Operator enters a partial name. Your app calls GET /vessels/search with ship_type=Ro-Ro and collects MMSI/IMO.
- You subscribe the chosen vessels to a refresh loop:
- Use POST /vessels/fleet with include_positions=true, include_routes=true every few minutes to redraw markers and ETAs.
- For port-side views, also call GET /port/expected-arrivals for the destination to build the inbound list.
- For each vessel:
- Render speed_knots, course_degrees, and age_minutes badges on the map tooltip.
- Show route.destination_port and route.eta in the card header; if missing, fall back to current_position.eta.
- Nightly, run GET /vessels/green and GET /vessels/analytics for each tracked MMSI to update emissions and reliability KPIs.
Common pitfalls and how to avoid them
- Assuming continuous AIS: coastal gaps happen. Use age_minutes and last_port_visits to maintain context during blackouts.
- Over-trusting static destinations: current_position.destination can be null or outdated. Prefer route.destination_port when available.
- Ignoring ship_type drift: vessels can be misclassified in third-party feeds. Here, filter by ship_type in search, but also validate dimensions (length_m/width_m) for Ro-Ro berth fit.
- Not normalizing names: treat name as non-unique; use MMSI/IMO for identity across systems.
FAQ
Q: What identifiers should I store to reliably track a Ro-Ro?
A: Store both IMO and MMSI when available. Use MMSI for AIS tracking calls, IMO for cross-system joins and static particulars.
Q: How fresh are positions, and how do I guard my UI?
A: Check current_position.age_minutes. If it exceeds your freshness threshold, show a stale badge or greyed marker and pause ETA alerts until a new fix arrives.
Q: Can I get multiple Ro-Ro positions in one call?
A: Yes. Use POST /vessels/fleet with a mixed list of imo/mmsi and include_positions=true (and include_routes=true if you need voyage context).
Q: How do I plan yard gates for the next 12–24 hours?
A: Combine GET /port/expected-arrivals for the target port with GET /vessels/track for your focus Ro-Ros. Prefer route.eta; if absent, derive ETA from distance_nm and speed_knots.
Q: Where can I test or automate multi-agent control over these endpoints?
A: Use the MCP to orchestrate multi-call workflows and agents interacting with the API.
Ship your Ro-Ro tracking workflow now. Get an API key, explore the docs, and wire up your first track request in minutes: Register, read the Documentation, and try the MCP to automate fleet and port intelligence tasks.





