Research operators often juggle dozens of vessels, science missions, and safety constraints, yet they lack a single, reliable source of AIS positions, voyage analytics, and fleet-wide context. By the end of this guide you’ll know exactly how to query research vessel positions in near real time, compute voyage statistics, monitor nearby traffic for safety, and roll up a live fleet view and CII emissions scoring—using one consistent REST API and one API key.
What you can build for research vessels with one API
vessels-api.com exposes a unified REST interface for global AIS and maritime intelligence. It’s designed for developers who need dependable endpoints and predictable payloads:
- 18 REST endpoints: vessel search, live AIS tracking, fleet operations, port intelligence, and IMO CII emissions.
- One API key and one base URL: https://vessels-api.com/api/V1. All auth via X-API-Key header.
- Consistent JSON envelope: {status, success, message, data} on every response.
- Global AIS coverage with near real-time refresh.
- 7-day free trial; scales from indie tools to enterprise research fleets.
In this article we’ll focus on the endpoints that matter most for research vessels:
- GET /vessels/track — live track + history + route + predicted ETA + weather.
- POST /vessels/fleet — batch positions and routes for multiple ships.
- GET /vessels/analytics — voyage analytics for a vessel or ad‑hoc fleet.
- GET /vessels/nearby — situational awareness around a lat/lon.
- GET /vessels/green — IMO CII metrics for ESG/compliance reporting.
Authentication and core patterns
All requests include your API key:
- Header: X-API-Key: YOUR_API_KEY
- Base URL: https://vessels-api.com/api/V1
Responses use a stable envelope with a data object that holds the payload you’ll render or store. Timestamps are UTC (ISO 8601). Distances are nautical miles (nm). Speeds are in knots. Pagination parameters for list-style endpoints include page and per_page (max 100).
Live research vessel tracking: route, positions, ETA, weather
Use GET /vessels/track to retrieve the current position, optional recent history (up to 168 hours), active route, predicted ETA, and optional weather.
- Required: one of imo or mmsi.
- Optional: hours (default 24; max 168), include_route, include_predicted_eta, include_weather.
Official sample (copy/paste)
The following request and response are provided as a reference track fixture for the documented MMSI 258785000.
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:31+00:00",
"age_minutes": 5100260,
"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
}
}
What to use in your app:
- data.current_position.latitude/longitude — plot on a map or alert on drift.
- data.current_position.speed_knots and course_degrees — detect transits vs stations.
- data.route.departure_port/destination_port/eta — build operational ETAs and port scheduling.
- data.last_port_visits — drive port call timelines in your mission logbook.
Python example: query a research vessel and render a dashboard row
import requests
from datetime import datetime
API_KEY = "YOUR_API_KEY"
URL = "https://vessels-api.com/api/V1/vessels/track"
params = {
"mmsi": "258785000",
"hours": 48 # up to 168
}
resp = requests.get(URL, headers={"X-API-Key": API_KEY}, params=params, timeout=20)
resp.raise_for_status()
payload = resp.json()["data"]
vessel = payload["vessel"]
pos = payload["current_position"]
route = payload.get("route") or {}
def fmt_time(s):
return s if not s else datetime.fromisoformat(s.replace("Z","+00:00")).isoformat()
row = {
"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"),
"navigational_status": pos.get("navigational_status"),
"position_time_utc": pos.get("timestamp_utc"),
"destination": pos.get("destination") or route.get("destination_port"),
"eta_utc": pos.get("eta") or route.get("eta"),
"last_departure_port": route.get("departure_port"),
"avg_speed_knots_route": route.get("avg_speed_knots")
}
print(row)
Tips for research operators:
- Use hours=168 to backfill a week of track breadcrumbs for post-mission analysis.
- include_weather=true can overlay metocean context for deck operations planning.
- Nulls are expected for docked or silent AIS periods; code defensively.
Fleet operations in one call: monitor all research assets
The POST /vessels/fleet endpoint returns positions and (optionally) routes for multiple vessels in a single request. This is ideal for a live “fleet board” that your shore team refreshes every 30–60 seconds.
cURL: batch two vessels
Response shape
Notes:
- Include both IMO and MMSI in your list; the API resolves whichever identifier you provide.
- Use the fleet summary to power a quick “at sea vs in port” KPI widget.
- Null position/route values indicate no recent AIS or no active voyage—keep your UI tolerant.
Voyage analytics for science missions and utilization
Research operators need to quantify transit distance vs on-station time, average speeds, and port calls to plan fuel, berths, and crew rotations. GET /vessels/analytics aggregates this for a single vessel, a port, or an ad‑hoc fleet.
- Required: type=vessel|port|fleet
- Conditional:
- type=vessel: imo or mmsi
- type=port: port_id
- type=fleet: mmsi_list (comma-separated)
- Optional: period=24h|7d|30d|90d
cURL: 7-day analytics for a vessel
Sample response (key fields)
How to use it:
- Compare total_distance_nm against planned survey lines to validate mission execution.
- Use total_time_in_port_hours to optimize layover windows for mobilization/demobilization.
- Track utilization ratios by period (e.g., station time vs transit using avg and max speeds with your own business logic).
Situational awareness around survey areas
Many research missions occur near shipping lanes. GET /vessels/nearby returns all vessels within a radius of a lat/lon in nautical miles. Use this to increase watchstanding safety and to de-conflict operations like ROV dives or CTD casts.
cURL: traffic within 30 nm of a station
Sample response snippet
Practical integrations:
- Create guard zones around your drift station; trigger alerts when a fast mover enters within 10 nm.
- Filter by ship_type to focus on large commercial traffic.
ESG and grant reporting: IMO CII for research vessels
For public agencies and universities, emissions transparency is increasingly required. GET /vessels/green estimates CO2 over a period and provides an IMO CII score and rating (A–E) based on MEPC.339(76). Use this to standardize internal reporting and grant applications.
cURL: 30-day CII snapshot
Sample response snippet
Combine CII output with /vessels/analytics to explain emission drivers by voyage distance, speed profiles, and port time.
Developer notes that save time
- Units: Positions are decimal degrees; distances are nautical miles; speeds are knots; times are UTC ISO 8601.
- Pagination: /vessels/search and similar list endpoints accept page and per_page (max 100). Store pagination cursors if you’re syncing catalogs.
- Caching & polling: For live maps, 30–60s polling is typical. Cache immutable histories by vessel and hour window to avoid re-downloading unchanged tracks.
- Null fields: AIS can be intermittent; always handle null for name, heading, route, and predicted_eta.
- Error handling: Check the top-level {status, success, message}. Status codes include 400 (invalid params), 401 (missing/invalid key), 404 (not found), 422 (out of range), 429 (rate limit), 500 (server error).
Putting it together: a lightweight research fleet dashboard
Here’s a quick blueprint for a control panel your ops team can ship in a day:
- Map layer: For each asset, GET /vessels/track to plot current_position and route. Refresh every 45s.
- Fleet KPI: POST /vessels/fleet to compute vessels_at_sea vs vessels_in_port and show occupancy.
- Safety ring: GET /vessels/nearby around the active station to list nearest 10 contacts sorted by distance_nm.
- Performance tab: GET /vessels/analytics weekly to show total_distance_nm, avg_speed_knots, and port_calls_count.
- ESG tab: GET /vessels/green monthly to snapshot CII rating and co2_tons.
Bonus: find and onboard a new research vessel
If you need to enroll a newly chartered vessel, use GET /vessels/search. You can search by name fragment with optional filters (e.g., ship_type, flag, build year, DWT/TEU if relevant).
cURL: fuzzy search by name and flag
Response snippet
Store the vessel’s IMO/MMSI from the response and feed it into /vessels/track, /vessels/fleet, and /vessels/analytics workflows.
Operational guardrails and quality tips
- Normalize identifiers: Persist both IMO and MMSI per asset; many downstream systems prefer IMO for long-term identity and MMSI for radio/AIS correlation.
- Mission segmentation: Use drops in speed_knots and course changes to infer on-station legs vs transit; persist segment boundaries for analytics.
- Alarms: Implement difference checks on position_age (or timestamp_utc drift) to detect AIS silence events.
- Time windows: For reproducible reports, request fixed windows (e.g., period=7d on Sundays at 00:00 UTC).
Frequently asked questions
Q: How fresh is the live AIS data?
A: Coverage is global with near real-time refresh. For live maps, poll on a 30–60s interval and debounce UI updates to avoid jitter.
Q: Can I request up to a week of historical positions?
A: Yes. /vessels/track supports hours up to 168. The position_history array returns breadcrumb points when available; cache them by vessel and time window.
Q: What’s the best way to track 50+ research vessels?
A: Use POST /vessels/fleet for a compact snapshot each refresh cycle. Fall back to per-vessel /vessels/track for detail pages or when you need route and last_port_visits.
Q: How do I integrate emissions into grant reporting?
A: Call /vessels/green for the relevant period (e.g., 30d or 1y). Combine co2_tons and cii.rating with /vessels/analytics distances to explain changes year over year.
Q: What does the response envelope look like everywhere?
A: Every endpoint returns {status, success, message, data}. Always check status/success and handle errors like 401 (auth), 404 (not found), 422 (param out of range), and 429 (rate limit).
Where to go next
Spin up a minimal fleet dashboard, wire in live tracks, and add analytics and CII in a single afternoon. Start by grabbing an API key, then skim the reference to choose the filters you need, and finally test requests in your terminal or your favorite HTTP client.





