OSV teams need live fleet positions, fast ETA updates, and clear port readiness signals to keep rigs supplied and minimize idle time. By the end of this guide, you’ll be able to query offshore supply vessel positions in near real time, fetch multi-ship snapshots for dispatch, compute voyage analytics, and monitor port congestion—using a single, consistent REST interface powered by AIS.
What you can build for offshore supply with one API
vessels-api.com provides a Transportation-focused REST API with global AIS coverage and a consistent JSON envelope on every response: {status, success, message, data}. You authenticate with one header (X-API-Key) against one base URL (https://vessels-api.com/api/V1), and you can cover the core OSV use cases with a handful of endpoints:
- Live track and recent history for dispatch and ETA checks: GET /vessels/track
- Batch fleet snapshot for on-call duty and ops rooms: POST /vessels/fleet
- Voyage analytics for performance reviews and contract SLAs: GET /vessels/analytics
- Geofenced awareness near rigs and staging areas: GET /vessels/nearby
- Port congestion snapshots when bunkering or resupply aligns with port calls: GET /ports/congestion
Each response includes units and fields that are friendly for Transportation applications: knots for speed, nautical miles for distance, ISO 8601 timestamps in UTC, and navigational status codes directly usable for watch lists.
Quick start: authenticate once, use everywhere
All requests require your API key in a single header. There is no OAuth dance, no per-endpoint token differences, and all responses share the same envelope.
X-API-Key: YOUR_API_KEY
Base URL for all endpoints:
https://vessels-api.com/api/V1
Network tips for operational dashboards:
- Cache static vessel metadata (dimensions, year built) client-side and refresh monthly.
- Poll dynamic endpoints like /vessels/track on a cadence matching your UI needs. For shift displays, 30–60 seconds is typical; for dispatch lists, 2–5 minutes is often enough.
- Use pagination on search endpoints (per_page up to 100) and apply backoff on 429 responses.
Live OSV tracking: current position, short history, and voyage context
OSV dispatch hinges on the latest position, speed-over-ground, and route context. Use GET /vessels/track with either IMO or MMSI to retrieve:
- current_position: lat/lon, speed_knots, course_degrees, navigational_status, timestamp_utc
- position_history: last N hours (up to 168) of points for breadcrumb trails
- route: departure_port, destination_port, ETA, distance_nm, avg_speed_knots
- last_port_visits: helpful for post-fixture analysis and crew changes
The following is the official sample for a documented MMSI (keep the header and URL exactly as shown when testing your integration):
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:05+00:00",
"age_minutes": 5098820,
"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
}
}
Fields to wire into your OSV dashboard:
- current_position.latitude and .longitude: draw the marker on your sea chart layer.
- current_position.speed_knots and .course_degrees: show live speed/course; ideal for DP vs. transit awareness.
- current_position.navigational_status: display as an icon or color (e.g., at anchor vs. underway).
- route.eta and route.destination_port: on-ramp to ETA alerts for rig rendezvous or port services.
- last_port_visits: feed your audit trail of port calls without scraping logs.
Python example: compute an OSV’s slack-to-ETA
The snippet below calls the same track endpoint and derives a basic “slack” metric to highlight whether an OSV is likely to arrive before or after a planned rig service window. All timestamps are UTC.
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=20)
resp.raise_for_status()
payload = resp.json()
if not payload.get("success"):
raise RuntimeError(f"API error: {payload.get('message')}")
data = payload["data"]
pos = data.get("current_position", {})
route = data.get("route", {}) or {}
print(f"MMSI {data['vessel'].get('mmsi')} at {pos.get('latitude')}, {pos.get('longitude')} "
f"{pos.get('speed_knots')} kn, COG {pos.get('course_degrees')}°, status {pos.get('navigational_status')}")
eta_iso = route.get("eta")
if eta_iso:
eta_dt = datetime.fromisoformat(eta_iso.replace("Z", "+00:00"))
now_utc = datetime.now(timezone.utc)
slack_minutes = int((eta_dt - now_utc).total_seconds() / 60)
print(f"Route ETA: {eta_iso} (slack {slack_minutes} minutes)")
else:
print("No ETA available on current route")
Fleet operations: one POST to snapshot dozens of OSVs
Operations managers often need the status of multiple OSVs at once—what’s at sea, what’s in port, and who is on approach to a location. Use POST /vessels/fleet to fetch positions and routes in bulk. This endpoint reduces N network calls into one structured response and includes a high-level rollup.
Key elements you’ll parse:
- data.fleet.vessels_at_sea vs. vessels_in_port: populate KPI cards in an ops room.
- data.vessels[].position: show all markers at once, without looping requests.
- data.vessels[].route: update a dispatch board with next port and ETA data.
Implementation details:
- Body accepts IMO and/or MMSI; pass whichever you maintain in your TMS or CMMS.
- Use include_routes for voyage context if you want a single payload for list and detail views.
- Error handling: if any vessel is missing, the endpoint returns 404 for that item; keep a per-vessel error state in your UI.
Analytics for OSV voyages: utilization, speed profiles, and port call counts
Use GET /vessels/analytics to aggregate voyage performance across windows like 24 hours or 7 days. For offshore supply, this helps answer, “How much steaming vs. time-in-port did we log this week?” or “Are we meeting max-speed guidelines between base port and field?”
Important fields to wire into your reporting widgets:
- statistics.total_distance_nm: nautical miles covered in the period.
- statistics.avg_speed_knots and max_speed_knots: compare to contract caps.
- statistics.port_calls_count and total_time_in_port_hours: plan crew, stores, and dockside services.
- statistics.ports_visited: tag your port rotations for line-of-business reporting.
Mode switches:
- type=vessel with imo or mmsi for a single OSV
- type=fleet with mmsi_list for multi-ship summaries (useful for weekly rollups)
- type=port with port_id for port-centric views relevant to base operations
Geofenced awareness near rigs and staging areas
When an anchor handler or PSV is inbound to a field, watch for nearby marine traffic with GET /vessels/nearby. This is useful for safety corridors, last-mile rendezvous, and transfer windows. You provide the lat/lon center and an NM radius (default 50, max 200).
Response highlights to render on your situational chart:
- data.vessels[].position.latitude/longitude/timestamp_utc: animate recent points.
- data.vessels[].distance_nm: sort by proximity to the rig or standby area.
- data.vessels[].speed_knots and navigational_status: quickly differentiate transiting vs. DP holding.
Use limit to cap the list for UI performance. If you need more than 50, paginate or increase the limit carefully to maintain refresh rates.
Port intelligence for OSV base calls
Even if your core operations are offshore, base ports can be chokepoints for bunkers, water, drilling mud, or deck cargo. For a live snapshot of berth and anchorage pressure plus wait-time statistics, call GET /ports/congestion with a UNLOCODE in the port_id parameter (e.g., ARBUE, SGSIN, NLRTM). Avoid guessing the values; parse the fields as provided:
- snapshot.vessels_in_anchorage and vessels_at_berth: quick-glance load at the port.
- statistics.avg_wait_time_hours_last_7d and max_wait_time_hours_last_7d: trend your risk of delay.
- statistics.avg_berth_time_hours_last_7d and port_calls_count: plan turnarounds.
Pair this with GET /port/expected-arrivals to understand inbound traffic that might compete for berth windows when you schedule resupply or crew change legs through a port.
Search and filtering for OSV rosters
When seeding your internal vessel directory, GET /vessels/search helps you find ships by name (fuzzy), IMO, or MMSI, with filters such as ship_type, flag, year built, and tonnage ranges. Typical OSV catalogs might filter by ship_type and year_built_to to narrow for class rules or DP capability lists.
Pagination notes:
- per_page max is 100; use pagination.current_page and pagination.last_page to iterate.
- Cache the canonical IMO/MMSI pair you choose to key your records. All downstream endpoints accept either identifier.
ESG overlay: CII scoring for contract and compliance teams
If your charterers or operators require visibility into emissions intensity, GET /vessels/green provides estimated emissions over a specified period with CII score and rating, based on IMO MEPC.339(76). For OSVs, pair this with voyage analytics to set operational caps or pick the greener asset when multiple hulls are available for a job.
Use fields like data.estimated_emissions.co2_tons and data.cii.rating to populate compliance dashboards. Present together with total_distance_nm so operational teams can normalize performance across similar missions.
Error handling, units, and reliability checks
Every endpoint returns standardized status and success fields. Common error codes you should handle:
- 400: Missing/invalid parameter (e.g., no imo or mmsi on a vessel call)
- 401: Invalid or missing X-API-Key (validate your header per request)
- 404: Vessel/port not found (keep a retry strategy or manual resolution queue)
- 422: Parameter out of range (e.g., nearby radius > 200 NM)
- 429: Rate limit exceeded (exponential backoff and jitter)
- 500: Server error (retry with circuit breaker)
Operational notes for Transportation teams:
- Speeds are knots; distances are nautical miles; times are ISO 8601 UTC.
- Some fields may be null where AIS does not report (e.g., heading_degrees or destination on certain transponders).
- Use age_minutes in current_position to detect stale AIS and flag a “last seen” badge in your UI.
Putting it together: a minimal OSV fleet board
Combine these calls to ship a functional on-call fleet board:
- Seed a roster: /vessels/search with filters for Offshore ship_type.
- Render a snapshot: /vessels/fleet with include_positions=true for markers and headings.
- Drill into a hull: /vessels/track for ETA and last_port_visits; cache the envelope for detail panes.
- Context around the field: /vessels/nearby centered on the rig’s coordinates (radius 20–30 NM).
- Plan port touches: /ports/congestion and /port/expected-arrivals when staging at base ports.
- Weekly report: /vessels/analytics type=fleet for voyage KPIs; optionally overlay /vessels/green for CII.
Reference: consistent JSON envelope
All responses from vessels-api.com follow the same envelope for fast integration:
Use status for HTTP-like semantics in client logs, success for branch logic, and message for human-readable hints. Always null-check optional elements (route, weather, predicted_eta) before rendering.
Production hardening tips
- Idempotent polling: prefer GET endpoints for periodic updates; keep POST /vessels/fleet for bulk refreshes at controlled intervals.
- Backoff on 429 and 500 with capped retries; track failure rate SLO in your observability stack.
- Geospatial indexing: store last known lat/lon in your DB to support server-side filtering and reduce frontend load.
- UI performance: pack markers with clustering by zoom level; only render breadcrumbs when a vessel row is selected.
- Data hygiene: when MMSI changes after refit, favor IMO as the durable key; the API accepts either.
FAQs
Q: How fresh is the live AIS data for OSVs?
A: The API provides global AIS coverage with near real-time refresh rates. Use current_position.timestamp_utc and age_minutes to display recency per vessel.
Q: Do I need different tokens per endpoint?
A: No. Authenticate every request with X-API-Key and the same base URL. There are no per-endpoint auth differences.
Q: Can I get multiple vessels in a single call?
A: Yes. Use POST /vessels/fleet and pass a list of IMO/MMSI identifiers. Include positions and routes as needed for your dashboard.
Q: How can I monitor congestion at a base port?
A: Call GET /ports/congestion with the UNLOCODE (e.g., ARBUE) and an optional period. Parse snapshot and statistics fields for operational planning.
Q: What about emissions reporting?
A: Use GET /vessels/green to retrieve estimated emissions and CII scores over 24h, 7d, 30d, or 1y windows, suitable for ESG dashboards and compliance checks.
Build your OSV fleet board, dispatch tools, and analytics in hours, not weeks. Start with the live tracking example above, expand to fleet snapshots and analytics, and keep iterating with a single, consistent API surface. Explore the Documentation, generate live calls from the MCP, and Register to get your key and ship your OSV tracking integration.





