Ro-Ro Vessel Tracking

Ro-Ro Vessel Tracking

Ro-Ro operators, logistics teams, and port coordinators need to know where each ship is, where it’s headed, and when it will berth—without stitching together brittle data sources. By the end of this guide, you’ll be able to track roll-on/roll-off vessels in near real time, build fleet dashboards, compute ETAs for logistics, and surface ESG/IMO CII insights using the vessels-api.com REST API.

Ro-Ro tracking: what matters operationally

Ro-Ro shipping is all about precise timing at ramps and berths. For each vessel you typically need:

Illustration: Ro-Ro Vessel Tracking
  • Current AIS position with speed and course to project arrival windows.
  • Recent route and last port calls to understand disruptions and port-state controls.
  • Port expected arrivals to align yard and gate operations for vehicles and trailers.
  • Fleet-level snapshots across multiple MMSIs to prioritize exceptions.
  • Emissions/efficiency signals (IMO CII) to support ESG reporting and charter-party obligations.

vessels-api.com provides 18 REST endpoints to handle these jobs with one API key and one base URL. Responses always follow the same JSON envelope: {status, success, message, data}, which makes client code simple and predictable.

API setup and request model

All requests use the X-API-Key header against the base URL https://vessels-api.com/api/V1. Most endpoints are GET; only /vessels/fleet is POST for batch operations. Units are nautical miles (nm) and knots. Timestamps are UTC ISO-8601. The consistent envelope means you’ll always check status/success and then read data.* fields.

  • Authentication: X-API-Key: YOUR_API_KEY
  • Base URL: https://vessels-api.com/api/V1
  • Response envelope: {status, success, message, data}
  • Refresh: near real time (global AIS)
  • Errors: 400/401/404/422/429/500 per the docs

Keep the following links handy while you build:

Core endpoints for Ro-Ro vessel tracking

1) Live track with route and last port calls: GET /vessels/track

Use this to power your per-vessel detail pages and alerting. It returns the current AIS position, optional position history, active route info, predicted ETA, and recent port calls. You can query by MMSI or IMO. For Ro-Ro, MMSI is commonly at hand from operations sheets and is the most direct key.

Official cURL and JSON (copy-pasteable):

curl -H "X-API-Key: YOUR_API_KEY" "https://vessels-api.com/api/V1/vessels/track?mmsi=258785000&hours=48"
{
    "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:53+00:00",
            "age_minutes": 5137820,
            "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 you’ll actually use:

  • data.current_position.latitude/longitude (map markers), speed_knots (delay risk), course_degrees (track line), timestamp_utc (staleness check).
  • data.route.departure_port, destination_port, avg_speed_knots for operational context and KPI charts.
  • data.last_port_visits[*] to build port call timelines and automatic pre-advice for terminals.
  • data.predicted_eta when available; otherwise, compute your own window using speed/remaining distance.

Parameters you’ll care about:

  • mmsi or imo required.
  • hours optional for position_history (default 24, max 168 for a 7-day lookback).
  • include_route, include_predicted_eta, include_weather toggles as needed.

2) Fleet-wide snapshots: POST /vessels/fleet

For a Ro-Ro control tower, you need to reduce tab-hopping. Batch multiple vessels to get positions and routes in one response, then color-code by at-sea/in-port.

Read data.fleet for quick KPIs (total_vessels, vessels_at_sea, vessels_in_port), and data.vessels[] for each unit’s position/route. This is perfect for a map view with aggregated counters and a sidebar showing ETAs.

3) ETAs and event feeds for ports: GET /port/expected-arrivals and GET /port/activity

When coordinating yard space and ramp scheduling, you’ll want a forward look. Use expected arrivals to list inbound Ro-Ro calls along with ETA and origin. For retrospective audits and SLA compliance, read activity to see recent arrivals/departures by port.

  • GET /port/expected-arrivals?port=PORT_ID → data.expected_arrivals[*].eta, vessel identifiers, and departure_port.
  • GET /port/activity?port=PORT_ID → data.arrivals[*] and data.departures[*] with timestamps and peer ports.

Pair these with /vessels/track for a detailed, per-vessel view when a ship is inside the T–24 hour window.

4) Voyage analytics for planning: GET /vessels/analytics

For lane planning and reliability metrics, you can pull aggregated voyage statistics per vessel or across a fleet mode. This helps validate timetables and turn-time targets for Ro-Ro corridors.

Fields like statistics.total_distance_nm, avg_speed_knots, and port_calls_count roll up the recent pattern. Use period to switch between 24h/7d/30d/90d.

5) ESG readiness with IMO CII: GET /vessels/green

More Ro-Ro contracts call for emissions disclosure. Pull the CII score and rating to populate dashboards and supplier questionnaires.

You’ll read data.cii.rating (A–E) and data.estimated_emissions.co2_tons to track progress and escalate underperformers.

Build a minimal Ro-Ro tracker in Python

The following script calls /vessels/track for a known Ro-Ro MMSI, extracts the current position, route context, and recent port calls, and prints a concise status line you can drop into Slack or a web widget.

import requests
from datetime import datetime, timezone

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://vessels-api.com/api/V1"

def iso_to_dt(s):
return datetime.fromisoformat(s.replace("Z", "+00:00")) if s else None

def track_roro(mmsi: str, hours: int = 48):
url = f"{BASE_URL}/vessels/track"
params = {"mmsi": mmsi, "hours": hours}
headers = {"X-API-Key": API_KEY}
r = requests.get(url, headers=headers, params=params, timeout=20)
r.raise_for_status()
payload = r.json()
if not payload.get("success"):
raise RuntimeError(f"API error: {payload.get('message')}")
d = payload["data"]
cp = d.get("current_position", {}) or {}
route = d.get("route", {}) or {}
last_ports = d.get("last_port_visits", []) or []

lat = cp.get("latitude")
lon = cp.get("longitude")
speed = cp.get("speed_knots")
course = cp.get("course_degrees")
when = cp.get("timestamp_utc")
ts = iso_to_dt(when)
age = cp.get("age_minutes")

dep = route.get("departure_port")
dest = route.get("destination_port")
avg_spd = route.get("avg_speed_knots")

last_port = last_ports[0]["port_name"] if last_ports else None

parts = []
parts.append(f"MMSI {mmsi}: ")
if lat is not None and lon is not None:
parts.append(f"pos {lat:.5f},{lon:.5f}")
if speed is not None:
parts.append(f"speed {speed} kn")
if course is not None:
parts.append(f"course {course}°")
if dest:
parts.append(f"dest {dest}")
if dep:
parts.append(f"dep {dep}")
if avg_spd is not None:
parts.append(f"avg {avg_spd} kn")
if ts:
now = datetime.now(timezone.utc)
parts.append(f"as of {ts.isoformat()} (age {age} min)")
if last_port:
parts.append(f"last port {last_port}")

print(" | ".join(parts))

if __name__ == "__main__":
track_roro("258785000", hours=48)

Notes:

  • The response envelope is checked before accessing data.*.
  • Speed/course are in knots/degrees true; timestamps are UTC. age_minutes helps you decide whether to down-weight stale points.
  • Add include_route=true or include_predicted_eta=true as needed; the default track call already returns route in the example above.

End-to-end Ro-Ro workflows

Fleet dashboard

  • Use POST /vessels/fleet to fetch 20–50 Ro-Ro MMSIs at once with include_positions=true.
  • Compute ETA windows from /vessels/track predicted_eta when present; otherwise derive from course/speed and last known waypoints.
  • Show aggregated counters from data.fleet to highlight workload by sea vs port.

Terminal pre-advice and yard allocation

  • Pull GET /port/expected-arrivals for the target port to list inbound Ro-Ro ships and ETAs.
  • For each inbound, call GET /vessels/track with hours=24 to show the live approach on a small map and confirm navigational_status transitions.
  • Combine last_port_visits info to infer prior ramp operations and likely handover delays.

Exception management and alerts

  • Trigger alerts when speed_knots drops below a threshold inside a geofence (e.g., approaches to a strait), or when timestamp_utc grows stale compared to age_minutes tolerance.
  • Leverage GET /vessels/analytics with period=24h to detect unusual loitering or excessive time_in_port_hours.

ESG/charter-party compliance

  • Schedule GET /vessels/green weekly with period=30d to watch CII scores/rating. Surface co2_tons and co2_per_nm for transparency.
  • Use GET /vessels/analytics to contextualize emissions per distance or per port call over 30–90d windows.

Production details that save time

  • Staleness: Always read data.current_position.timestamp_utc and age_minutes. If the point is too old for your use case, flag it in the UI or fall back to the last reliable position window.
  • Units: Distances are nautical miles; speeds in knots; times in UTC. Display local times by converting with the port timezone from GET /ports or GET /ports/data.
  • Pagination: Vessel search and some list endpoints return pagination info inside data.pagination; cap per_page at 100.
  • Retries: Handle 429s with exponential backoff. For 404s (“Vessel not found”), verify the identifier and consider searching by name with GET /vessels/search.
  • Search normalization: For Ro-Ro classed ships with common names, search by IMO/MMSI when possible; use name fuzzy matching only as a fallback with optional filters like ship_type or flag.
  • Batching: Prefer POST /vessels/fleet over N separate calls to /vessels/track for control tower views; it reduces latency and rate consumption.
  • Consistency: Every endpoint returns {status, success, message, data}. Fail fast on success=false before dereferencing deeper fields.

Vessel discovery for Ro-Ro fleets

If you only know part of a name or you’re onboarding a chartered Ro-Ro vessel without a confirmed MMSI, use /vessels/search. You can filter by flag, ship_type, year_built ranges, or TEU/DWT constraints when relevant.

The response includes data.vessels[*] with identifiers and dimensions. Persist MMSI/IMO in your own database and use them as primary keys going forward.

Example: derive an arrival window for a Ro-Ro call

Here’s a simple approach you can embed into your backend:

  • Call GET /vessels/track with include_route=true and include_predicted_eta=true.
  • If data.predicted_eta is non-null, trust it as the center of your window.
  • If null, combine current_position.speed_knots with a last-mile distance estimate to the pilot boarding area to project a range (e.g., base on avg_speed_knots when speed is erratic).
  • Cross-check port approach congestion using GET /ports/data for live vessel counts at the destination.

When the ship enters your T–6 hour window, tighten the ETA based on short-term speed stability and navigational_status transitions.

FAQ

Q: What identifiers should I store for Ro-Ro ships?
A: Store both MMSI and IMO when available. MMSI is used for radio/AIS and may change; IMO is persistent. The API supports either in core endpoints like /vessels/track and /vessels/green.

Q: How often should I poll for live positions?
A: It depends on your use case and map load. For en-route visibility, 2–5 minute polling is common. Use age_minutes to avoid redrawing stale positions and prefer /vessels/fleet for batches.

Q: Can I get historical tracks for post-voyage analysis?
A: Yes. /vessels/track supports a position_history window up to hours=168 (7 days). For aggregates beyond that, use /vessels/analytics with period=30d or 90d.

Q: How do I align times with local port timezones?
A: Timestamps are UTC. Retrieve port timezone via GET /ports or GET /ports/data and convert in your application before presentation.

Q: How are CII ratings expressed?
A: /vessels/green returns data.cii.rating in A–E per IMO MEPC.339(76), with supporting fields like co2_tons and co2_per_nm for the selected period.

Start building your Ro-Ro tracking and operations layer with a single, consistent API surface. Get your key, open the Documentation, and try the endpoints in the MCP. When you’re ready, Register and ship your Ro-Ro visibility dashboard in hours, not weeks.

Ready to get started?

Get your API key and start tracking vessels in minutes.

Get API Key

Related posts