You have an MMSI and need to answer concrete questions fast: Where is that ship right now? Where has it been in the last 24–168 hours? What’s its route, ETA, and is it near your port? By the end of this guide you’ll be able to track any vessel by MMSI with live AIS data, pull historical positions, compute voyage analytics, and fold that data into dashboards, alerts, and workflows using vessels-api.com.
What MMSI tracking gives you—and how to wire it up quickly
A Maritime Mobile Service Identity (MMSI) uniquely identifies a vessel on AIS. With a single MMSI you can retrieve:
- Current position: latitude/longitude, course, speed, navigational status, timestamp (UTC)
- Position history: up to 168 hours of AIS points
- Active route: departure port, destination port, ETA, distance, and average speed
- Aggregated analytics: total distance, port calls, time in port over a window (24h–90d)
- Nearby vessels: discover traffic density or proximity events around a point of interest
- CII emissions snapshot: estimated CO2 and IMO CII rating for ESG reporting
All of this is available through one REST API, one base URL, and a single API key header:
- Base URL: https://vessels-api.com/api/V1
- Authentication: X-API-Key: YOUR_API_KEY
- Response envelope: {"status", "success", "message", "data"} on every endpoint
Below we’ll focus on the endpoints you’ll actually use to track a ship by MMSI: /vessels/search, /vessels/track, /vessels/nearby, /vessels/analytics, plus /vessels/fleet and /vessels/green for multi-ship ops and ESG.
Find the correct MMSI (or confirm it) with /vessels/search
If you only know a vessel’s name (or need to confirm MMSI vs. IMO), start here. The search supports fuzzy name matching and direct identifiers, with optional filters to narrow by flag, type, tonnage, or build year.
cURL
curl -H "X-API-Key: YOUR_API_KEY" "https://vessels-api.com/api/V1/vessels/track?mmsi=258785000&hours=48"
Sample response (truncated)
{
"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:27+00:00",
"age_minutes": 5103140,
"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
}
}
Notes that save time:
- Pagination: per_page max is 100. Use page to walk large result sets.
- Identifiers: If you already have the MMSI, you can pass it as query. For name-only lookups, add filters like flag or ship_type to home in on the correct target.
Get current position and history by MMSI with /vessels/track
This is the core of MMSI tracking. Provide an MMSI and get current AIS position, optional 24–168 hours of history, route, predicted ETA, and more. Timestamps are ISO-8601 with timezone (UTC recommended for processing).
Official cURL sample (copy-paste)
Official JSON sample (verbatim)
How to use these fields
- data.vessel: Identifiers you can cache against your internal ID.
- data.current_position: Point-in-time AIS with navigational_status and age_minutes. Use timestamp_utc for ordering and staleness checks; age_minutes is a quick health metric.
- data.position_history: When non-empty (set hours up to 168), plot track lines on your map or compute speed averages.
- data.route: Useful for ETA/status cards in dashboards. distance_nm may be null when not inferred from AIS; guard your UI accordingly.
- data.last_port_visits: Build port call timelines or compliance evidence, sorted most recent first.
Python example: tracking by MMSI and deriving a status label
import requests
from datetime import datetime, timezone
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://vessels-api.com/api/V1"
def get_track(mmsi: str, hours: int = 24):
url = f"{BASE_URL}/vessels/track"
params = {"mmsi": mmsi, "hours": hours}
r = requests.get(url, headers={"X-API-Key": API_KEY}, params=params, timeout=20)
r.raise_for_status()
return r.json()
def label_status(current):
# Simple, defensive status labeling for dashboards
speed = current.get("speed_knots")
status = current.get("navigational_status")
if speed is None:
return "Unknown"
if speed > 0.5:
return "Under way"
# Map AIS code 5 to "Moored/At anchor" per your internal legend
if status == 5:
return "Moored"
return "Stopped"
def main():
data = get_track("258785000", hours=48)
current = data["data"]["current_position"]
vessel = data["data"]["vessel"]
ts = current.get("timestamp_utc")
ts_dt = datetime.fromisoformat(ts.replace("Z", "+00:00")) if ts else None
print(f"MMSI: {vessel.get('mmsi')} IMO: {vessel.get('imo')}")
print(f"Pos: {current.get('latitude')}, {current.get('longitude')} Speed: {current.get('speed_knots')} kn")
print(f"Course: {current.get('course_degrees')}° Nav status: {current.get('navigational_status')}")
print(f"Timestamp (UTC): {ts_dt}")
print(f"Status label: {label_status(current)}")
route = data["data"].get("route") or {}
print(f"Route: {route.get('departure_port')} → {route.get('destination_port')} ETA: {route.get('eta')}")
if __name__ == "__main__":
main()
Implementation details:
- Hours: default is 24, max is 168. Use smaller windows for frequent refreshes to keep payloads light.
- Null safety: Some fields may be null; never assume distance, heading, or destination is populated.
- Timestamps: ISO 8601 with offset. Coerce to UTC for consistent math and comparisons.
Discover traffic around a point with /vessels/nearby
When you need situational awareness—e.g., vessels within 30 NM of a pilot station—query by coordinates and optional radius and type filter.
cURL
Sample response (truncated)
Good to know:
- Radius default is 50 NM; max is 200 NM.
- Use ship_type and limit to tailor results to your operational picture.
Summarize a voyage window with /vessels/analytics
For dashboards and incident reviews, you often need aggregate stats, not raw tracks. /vessels/analytics gives totals across a time window for a single vessel, a port, or a fleet. Set type=vessel and pass either imo or mmsi for per-ship analytics.
cURL
Sample response
Use this for:
- Weekly rollups in fleet operations meetings
- SLAs on transit times and time-in-port
- Alerting when max_speed_knots or port_calls_count deviates from norms
Operate at scale with /vessels/fleet (batch) and /vessels/green (CII)
When tracking more than a handful of ships, fetch multiple positions and routes in one round trip. And if you report emissions or monitor compliance, attach CII scoring to the same objects in your data model.
Batch fleet positions and routes
/vessels/fleet accepts an array of IMO and/or MMSI, returning position and optional route for each.
cURL
Sample response (truncated)
Attach ESG signals with IMO CII via /vessels/green
Get estimated emissions and an IMO CII rating over a window you choose (24h–1y). Ratings follow IMO MEPC.339(76), with A best and E worst.
cURL
Sample response
Common pairing: call /vessels/fleet for your dashboard list, then fetch /vessels/green in parallel to overlay emissions badges. Cache CII for at least a day to minimize chatter.
Designing a reliable “Track by MMSI” feature
Below is a checklist of choices you can make up front to save time as your usage scales:
- Refresh cadence: For live maps, poll /vessels/track every 60–180 seconds per vessel; bump to 5–10 minutes for strategic views.
- History windows: Keep hours small (e.g., 6–24) for frequent updates. For analyses, request 48–168 hours on-demand when users open a “voyage” panel.
- Staleness: age_minutes tells you how fresh the last AIS is. If above a threshold (e.g., 120), gray out the icon or show “signal aged.”
- Null-tolerant UI: Destination, eta, distance_nm, heading_degrees can be null. Avoid breaking layouts when data is unavailable.
- Identifiers: Store both IMO and MMSI. MMSI can change in some operational scenarios; IMO is persistent across a ship’s life.
Error handling and limits
Every response includes status, success, and message. Handle these cases explicitly:
- 400: Missing/invalid parameter (e.g., absent mmsi)
- 401: Invalid or missing X-API-Key (check header spellings and scope)
- 404: Vessel not found (typo in MMSI or not in catalog yet)
- 422: Parameter out of range (e.g., hours > 168, radius > 200)
- 429: Rate limit exceeded (back off, jitter, and retry)
- 500: Server error (retry with exponential backoff)
Practical patterns:
- Cache immutable data (vessel particulars) for days; cache semi-static aggregates (analytics, green) for hours; keep live positions uncached or short-lived (1–5 minutes).
- Use ETags or timestamp gating in your client to avoid redundant refreshes on unchanged data.
Common use cases you can ship quickly
- Operations dashboard: Use /vessels/fleet for the list and per-card positions; open a side panel that calls /vessels/track with hours=24 for a sparkline and ETA.
- Logistics ETAs: From /vessels/track, prefer route.eta. If predicted_eta is present, use it as a model-derived supplement. Display both with provenance when they differ.
- Port ops watch: Call /vessels/nearby centered on pilot stations with radius=30–50 NM and filter by ship_type to prepare tugs and pilots.
- Compliance and ESG: Attach /vessels/green to each tracked MMSI, log daily snapshots, and alert when rating slips to D/E.
- Post-incident review: /vessels/analytics type=vessel over 7d/30d to summarize distance, speeds, and time in port around the event window.
End-to-end MMSI workflow: putting it together
- Identify the target: If you have the name, use /vessels/search with query and filters to confirm MMSI and IMO.
- Track live: Poll /vessels/track with the MMSI and a suitable hours window for your view. Render current_position and a polyline from position_history.
- Contextualize: Add route details (destination_port, eta) near the vessel label and a compact port call history list.
- Summarize: For weekly or monthly overviews, fetch /vessels/analytics with type=vessel and the same MMSI.
- Scale: When you have many ships, switch to /vessels/fleet for batch position and route pulls, and hydrate detail views on demand.
- Enrich: Attach /vessels/green periodically to fuel compliance and sustainability features.
Developer references and tools
- Documentation for parameters, fields, and additional endpoints like ports and expected arrivals.
- MCP for machine-readable contract and integration scaffolding.
FAQ
Q: Do I need both IMO and MMSI to track a ship?
A: No. /vessels/track accepts either imo or mmsi. When you have both, pass either and store both in your system for resilience.
Q: How fresh is the live AIS data?
A: Responses include timestamp_utc and age_minutes in current_position. Use age_minutes to determine how recent the AIS update is for your UI and alerts.
Q: Can I get more than 24 hours of history?
A: Yes. Set hours up to 168 (7 days). For very long tracks, prefer aggregated analytics via /vessels/analytics to control payload size.
Q: What does navigational_status represent?
A: It’s the AIS navigational status code as transmitted by the vessel. Use your own mapping to user-facing labels (e.g., 0=Under way, 5=Moored) if desired.
Q: How should I handle null fields like destination or distance_nm?
A: Treat them as “unknown” states. Always null-check route and weather fields, and fall back to historical behavior or omit UI elements when data isn’t present.
Build your MMSI tracking in hours, not weeks
You can start with a single cURL and grow into a full fleet dashboard using the same consistent API model. Use /vessels/track for live position and history, /vessels/analytics for rollups, /vessels/nearby for situational awareness, and /vessels/fleet plus /vessels/green to scale across operations and compliance. Get the details in the Documentation, then generate an API key and start testing. Register and wire up your first MMSI request today. For programmatic scaffolding and schema references, see the MCP.




