You need reliable AIS data to track an offshore supply vessel (OSV), calculate live ETAs to offshore fields and ports, monitor fleet activity at a glance, and feed operations systems with positions, routes, and compliance metrics. By the end of this article, you’ll be able to search for an OSV, stream its live track and recent route, batch-query a working fleet, compute voyage analytics, and pull port congestion intel—using a single REST API and a single API key.
Why developers track OSVs with Vessels API
Offshore supply vessels operate in dynamic environments—short voyages, repeated field shuttles, fast turnarounds, and weather-sensitive schedules. Vessels API aligns to that reality:
- 18 REST endpoints unified under one base URL and one API key (no OAuth).
- Consistent JSON envelope on every response: {status, success, message, data}.
- Global AIS coverage with near real-time refresh cadence for live tracking.
- Fit-for-purpose endpoints for vessel search, live position/history, fleet ops, port intelligence, and IMO CII emissions.
- Targets developers, startups, fleet and port ops, and ESG/compliance teams building transportation workflows.
Base URL: https://vessels-api.com/api/V1. Authenticate every request via the X-API-Key header.
Core endpoints to track an Offshore Supply Vessel
For an OSV tracking workflow, start with these endpoints:
- GET /vessels/search — identify the vessel (by name, IMO, or MMSI) and filter by vessel type or flag.
- GET /vessels/track — get the live position, up to 168 hours of position history, current route, and predicted ETA.
- POST /vessels/fleet — batch positions and routes for many vessels in one shot (bridge dashboards, dispatch monitors).
- GET /vessels/analytics — voyage summaries such as total distance and port calls over time windows (24h, 7d, etc.).
- GET /ports/congestion — real-time congestion and wait-time statistics for a target port (e.g., hubs supporting offshore fields).
- GET /vessels/green — CII scoring for ESG or compliance dashboards.
Search: resolve your OSV’s identity before tracking
When you onboard a new vessel, you might start from a partial name or region. Use search to resolve to IMO or MMSI before tracking.
Endpoint
GET /vessels/search
Parameters include query (name, IMO, or MMSI) plus optional filters such as ship_type, flag, and build year ranges. Pagination is supported via page and per_page (max 100).
cURL example
curl -H "X-API-Key: YOUR_API_KEY" "https://vessels-api.com/api/V1/vessels/track?mmsi=258785000&hours=48"
Use cases for OSVs:
- Resolve a working list of supply vessels calling a specific basin (filter by flag or ship_type).
- Match legacy MMSI/IMO maps when migrating from spreadsheets into an automated tracking pipeline.
Track: live position, recent history, route, predicted ETA, and last port visits
This is the workhorse endpoint for day-to-day OSV situational awareness. You can fetch just the live point, or include hours of history plus the active route and ETA prediction for logistics scheduling.
Endpoint
GET /vessels/track
Required: an identifier (imo OR mmsi). For OSV cadence, set hours between 24 and 168 to trace field shuttles. Optional include_route, include_predicted_eta, and include_weather let you enrich the context when needed.
Official sample: OSV track by MMSI (copy/paste)
{
"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:16+00:00",
"age_minutes": 5119040,
"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
}
}
How to use the fields:
- current_position: latitude/longitude in decimal degrees; speed_knots; course_degrees; navigational_status (integer code); timestamp_utc in ISO 8601 (UTC).
- route: departure_port, destination_port, eta, and avg_speed_knots help you compare against your job schedule.
- last_port_visits: recent events to support KPIs (e.g., turnarounds, dwell).
- position_history: request up to 168 hours when you need recent tracks for HSE or audit; keep hours small for lighter payloads and faster refresh.
JavaScript: call track and derive a dashboard card
async function fetchOsvTrack() {
const url = "https://vessels-api.com/api/V1/vessels/track?mmsi=258785000&hours=48";
const res = await fetch(url, {
headers: { "X-API-Key": "YOUR_API_KEY" }
});
if (!res.ok) {
throw new Error(`HTTP ${res.status}`);
}
const json = await res.json(); // { status, success, message, data }
const d = json.data;
const pos = d.current_position;
const route = d.route;
return {
mmsi: d.vessel.mmsi,
lat: pos.latitude,
lon: pos.longitude,
speedKn: pos.speed_knots,
courseDeg: pos.course_degrees,
navStatus: pos.navigational_status,
timestampUtc: pos.timestamp_utc,
destination: pos.destination || (route ? route.destination_port : null),
eta: pos.eta || (route ? route.eta : null),
lastPorts: d.last_port_visits || []
};
}
fetchOsvTrack()
.then(card => console.log("OSV card:", card))
.catch(err => console.error("Track fetch failed:", err));
Notes:
- All timestamps are UTC in ISO 8601 format.
- Units: nautical miles for distances, knots for speeds, degrees for headings/courses.
- Always check the {status, success, message} fields to short-circuit error handling.
Fleet: monitor multiple OSVs in one request
When you run a dozen OSVs servicing the same field, batch them to reduce round-trips and coordinate dispatch decisions with a single snapshot.
Endpoint
POST /vessels/fleet
Body includes a list of vessels with imo or mmsi and booleans for include_positions and include_routes. The response returns per-vessel position/route plus an aggregate fleet summary—helpful for “at sea” vs “in port” counts on a wallboard.
cURL example
Practical use:
- Refresh a fleet grid every 30–90 seconds during active ops; use ETag/If-None-Match or a small cache TTL to minimize bandwidth when no changes occur.
- Apply your own “ready state” rule based on speed_knots and last_port_visits to prioritize vessels for the next run.
Analytics: voyage statistics to tune OSV utilization
For short-cycle OSV operations, it’s useful to roll up distance, speeds, and port call counts by vessel or fleet for the last 24 hours to 90 days.
Endpoint
GET /vessels/analytics
Switch mode via type=vessel|port|fleet. For per-OSV stats, pass type=vessel with imo or mmsi and choose a period=24h|7d|30d|90d. The statistics payload includes:
- total_distance_nm
- avg_speed_knots
- max_speed_knots
- port_calls_count
- total_time_in_port_hours
- ports_visited
cURL example
Use this to benchmark cycle times by field, track port calls across the week, and estimate diesel consumption proxies when combined with speeds and distances.
Port intelligence: stay ahead of supply chain slowdowns
OSVs cycle through regional ports for crew changes, provisions, or equipment. Use port endpoints to anticipate ETAs and plan berthing or truck rendezvous.
Congestion snapshot
GET /ports/congestion requires a UNLOCODE (e.g., ARBUE for Buenos Aires, SGSIN for Singapore, NLRTM for Rotterdam). The response includes a snapshot of vessels in anchorage vs at berth and time-based statistics (e.g., avg_wait_time_hours_last_7d). Do not rely on static numbers; query when you need the latest state.
Expected arrivals
GET /port/expected-arrivals lists vessels inbound to a port with ETA and origin (useful to stage pilots or quayside equipment).
Pair congestion with expected arrivals to decide if you should reroute a resupply or push departure by several hours to avoid idle anchorage time.
ESG and compliance for OSVs: CII scoring
Many offshore operators now include emissions monitoring on their OSV dashboards. The CII endpoint surfaces a score and A–E rating for a chosen period.
Endpoint
GET /vessels/green
Required: imo OR mmsi. Optional: period=24h|7d|30d|1y (default 30d). Response includes estimated_emissions (co2_tons and co2_per_nm) plus cii {score, rating, year, regulation_reference} based on IMO MEPC.339(76).
cURL example
Practical OSV flow: compute CII monthly, flag D/E ratings for maintenance checks or operational changes (e.g., speed caps on transits).
Putting it together: an OSV operations loop
Here’s a pragmatic sequence you can ship into a control room app:
- Resolve IDs once with /vessels/search and store IMO/MMSI with your job cards or voyage plans.
- Pull live context every 30–90s with /vessels/track (hours=24 for recent history). Use route.eta and current_position.speed_knots to color-code “on time,” “risk,” or “late.”
- For multiple boats, consolidate with /vessels/fleet to drive a single screen and cut network calls.
- Call /vessels/analytics nightly for period=7d or 30d to update utilization KPIs and cycle-time histograms.
- Check /ports/congestion and /port/expected-arrivals before committing a departure to avoid anchorage queues.
- Score monthly with /vessels/green to track ESG posture and intervene on high-emitting patterns.
Operational details that save time
- Authentication: always include X-API-Key: YOUR_API_KEY. There is no OAuth or per-endpoint token difference.
- Envelope: every response follows {status, success, message, data}. Check success first; branch on status for retries vs hard failures.
- Time and units: timestamps are UTC ISO 8601; speed in knots; distances in nautical miles; courses/headings in degrees.
- History windows: /vessels/track supports hours up to 168. Large windows mean larger payloads—tune based on your dashboard refresh cycle.
- Pagination: /vessels/search returns pagination info in data.pagination. Respect per_page max 100.
- Error handling: 400 for parameter issues, 401 for invalid/missing key, 404 not found, 422 out-of-range parameter, 429 rate limit exceeded, 500 server error. Exponential backoff on 429/500; fix inputs for 400/422.
- Data freshness: position timestamps include timestamp_utc and may include age_minutes to help your UI represent stale vs fresh points.
Python: fetch an OSV track and normalize for storage
import requests
from datetime import datetime, timezone
API_KEY = "YOUR_API_KEY"
MMSI = "258785000"
def iso_to_dt(s):
return datetime.fromisoformat(s.replace("Z", "+00:00")).astimezone(timezone.utc) if s else None
def get_track(mmsi):
url = f"https://vessels-api.com/api/V1/vessels/track?mmsi={mmsi}&hours=48"
r = requests.get(url, headers={"X-API-Key": API_KEY}, timeout=20)
r.raise_for_status()
j = r.json() # {status, success, message, data}
if not j.get("success"):
raise RuntimeError(f"API error: {j.get('message')}")
d = j["data"]
pos = d.get("current_position") or {}
route = d.get("route") or {}
return {
"mmsi": d.get("vessel", {}).get("mmsi"),
"imo": d.get("vessel", {}).get("imo"),
"lat": pos.get("latitude"),
"lon": pos.get("longitude"),
"speed_knots": pos.get("speed_knots"),
"course_degrees": pos.get("course_degrees"),
"navigational_status": pos.get("navigational_status"),
"timestamp_utc": pos.get("timestamp_utc"),
"departure_port": route.get("departure_port"),
"destination_port": route.get("destination_port"),
"eta_utc": route.get("eta") or pos.get("eta"),
}
if __name__ == "__main__":
track = get_track(MMSI)
print(track)
Designing a robust OSV tracking service
- Polling cadence: align refresh intervals to operational needs. For tight approach windows, 30–60s; for open sea, longer intervals reduce load.
- Selective hydration: toggle include_route/include_predicted_eta/include_weather only when you need them to keep payloads small.
- Caching: store the last-good response with a short TTL. If a poll fails transiently, render cached data with a visible “stale” badge keyed off timestamp_utc.
- Data model: persist vessel identity (imo/mmsi), last 24h traces, last_port_visits, and latest route to power “resume state” UX after reconnection.
- Backfill: for incident review, request hours up to 168 and write to a time-series store keyed by MMSI+timestamp.
Related endpoints worth knowing
- GET /ports — the catalog (248 ports) with coordinates and timezones, helpful for map labeling or time conversions.
- GET /ports/data — single-port details including live vessel counts.
- Legacy endpoints (/vessel/info, /vessel/position, etc.) — stable, but prefer /vessels/* for richer, newer payloads.
FAQ
How do I track an OSV if I only know its name?
Use GET /vessels/search with query set to the vessel name, optionally filter by ship_type or flag, then take the returned IMO or MMSI into GET /vessels/track.
What’s the best way to monitor 10–20 OSVs at once?
Use POST /vessels/fleet with include_positions (and include_routes if needed). This reduces latency and request volume versus individual polls.
How do I know if the position is fresh?
Use current_position.timestamp_utc and, when present, age_minutes to compute staleness. Display a freshness badge in your UI and fall back to cached values when necessary.
Can I get predicted ETAs to berths or staging areas?
Yes. /vessels/track supports include_predicted_eta and returns route.eta. Compare predicted ETA with port congestion to refine job scheduling.
How do I integrate emissions scoring for OSVs?
Call GET /vessels/green with the IMO or MMSI. Store cii.score and cii.rating for the period you care about (e.g., 30d) and flag vessels with D/E ratings for follow-up.
Next steps
Build your OSV tracker with the endpoints above, keeping payloads tight and polling cadence aligned with operations. Explore the full surface area here: Documentation. Try interactive tools and integrations via the MCP. When you’re ready to ship, get your API key and start your implementation: Register.




