You need to track a tugboat reliably: where it is right now, where it’s headed, how fast it’s moving, and what it has done around nearby ports. By the end of this guide, you will query a tug’s live AIS position, pull 48-hour context, find nearby vessels at an operation zone, and wire a lightweight fleet view—using the same base URL, the same header, and consistent JSON across endpoints.
What you get with a single API key
Vessels API exposes 18 REST endpoints over one base URL and one header. For tugboat tracking and port operations in Transportation use cases, these are the workhorses:
- GET /vessels/track — real-time position, up to 168h of history, route, predicted ETA, and last port calls.
- GET /vessels/search — locate a tug by name, IMO, or MMSI with optional ship_type filter.
- GET /vessels/nearby — situational awareness around a lat/lon in nautical miles (NM).
- POST /vessels/fleet — batch positions and routes for multiple tugs in one shot.
- GET /ports/congestion — port congestion snapshot and wait-time statistics to plan assists.
Base URL: https://vessels-api.com/api/V1. Authenticate with the X-API-Key header on every call. Responses share a consistent JSON envelope: {status, success, message, data}.
Track a tugboat: live AIS and 48-hour context
Use GET /vessels/track to retrieve the current position and voyage context of a tug by MMSI or IMO. For this tutorial, we’ll use the documented MMSI fixture. Note: positions are expressed in latitude/longitude; speeds in knots; course/heading in degrees; timestamps are UTC.
Official cURL example (copy/paste)
curl -H "X-API-Key: YOUR_API_KEY" "https://vessels-api.com/api/V1/vessels/track?mmsi=258785000&hours=48"
Official JSON response (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:39+00:00",
"age_minutes": 5120480,
"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
}
}
Field highlights for tugboat operations:
- data.current_position.latitude/longitude — pin the tug on your map in WGS84.
- speed_knots and course_degrees — feed motion vectors for docking/escort UIs.
- navigational_status — AIS nav state (integer). Useful to filter active vs. moored tugs.
- timestamp_utc — ISO 8601 UTC. Cache-aware clients should keep this as the freshness watermark.
- route and last_port_visits — plan assist windows and after-action logs around port calls.
Python: parse the same response
import requests
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://vessels-api.com/api/V1"
params = {
"mmsi": "258785000",
"hours": 48
}
r = requests.get(f"{BASE_URL}/vessels/track", headers={"X-API-Key": API_KEY}, params=params)
r.raise_for_status()
payload = r.json()
if not payload.get("success"):
raise RuntimeError(payload.get("message"))
v = payload["data"]["vessel"]
pos = payload["data"]["current_position"]
print("MMSI:", v.get("mmsi"))
print("IMO:", v.get("imo"))
print("Lat/Lon:", pos.get("latitude"), pos.get("longitude"))
print("Speed (kn):", pos.get("speed_knots"))
print("Course (deg):", pos.get("course_degrees"))
print("Nav status:", pos.get("navigational_status"))
print("Timestamp (UTC):", pos.get("timestamp_utc"))
Find the tug first: search by name, MMSI, or vessel type
If you don’t have MMSI or IMO on hand, start with GET /vessels/search. You can fuzzy-search by name and filter by ship_type=Tug. Results are paginated with page and per_page (max 100).
Key response elements include:
- data.vessels — list of matches with identifiers (imo, mmsi), dimensions, and year_built.
- data.pagination — use current_page, per_page, total, last_page to page through results.
Workflow tip: once you have the tug’s MMSI from search, call /vessels/track in the same process to fetch live AIS and route context.
Operational awareness: which vessels are near the tug’s job site?
When planning a harbor assist or escort, GET /vessels/nearby offers a proximity snapshot. Provide latitude, longitude, and an optional radius in NM (default 50, max 200). You can limit or filter by ship_type to focus on traffic that impacts tug routing.
You’ll receive:
- data.center and radius_nm — input echo for map overlays.
- data.vessels[] — each entry includes position.timestamp_utc, speed_knots, course_degrees, navigational_status, and distance_nm from your center.
Practical use: render this feed as a ringed overlay on your operations map to deconflict tug movements with inbound tankers and feeder ships.
Manage multiple tugs: a single POST for fleet state
Dispatchers often track several tugs. POST /vessels/fleet packs batch positions and optional routes into a single call. Include IMO or MMSI tuples per vessel.
Response notes:
- data.fleet — aggregate counts: total_vessels, vessels_at_sea, vessels_in_port.
- data.vessels[] — normalized tuples with identifiers, position, and route for per-tug panels.
Tip: if you maintain your tug list server-side, schedule this call every N seconds, then emit WebSocket updates to the front-end. Use the current_position.timestamp_utc and a light in-memory cache to avoid redundant map repaints.
Plan assists against port congestion
Tug availability hinges on port traffic. Use GET /ports/congestion to understand anchorage vs. berth load and recent wait-time statistics. Supply a valid UNLOCODE in port_id (e.g., ARBUE, SGSIN, NLRTM) and an optional period of 24h, 3d, or 7d.
You’ll receive snapshot.vessels_in_anchorage and vessels_at_berth, plus statistics such as avg_wait_time_hours_last_7d and port_calls_count. Integrate this with /vessels/track to time tug dispatches against peak arrivals.
Wire it together: a tug dashboard architecture
With four endpoints, you can assemble a practical tug-ops view:
- Identity resolution: /vessels/search (query by name, filter ship_type=Tug) → MMSI/IMO.
- Live tracking: /vessels/track (per tug) → map markers, vectors, last-port context.
- Local picture: /vessels/nearby (per job site) → traffic heat, deconfliction.
- Fleet snapshot: /vessels/fleet (batch) → ops board with status counters.
- Port context: /ports/congestion (UNLOCODE) → assist planning vs. queues.
Every response follows the same JSON envelope. Handle errors by checking HTTP status and payload.success. Common error codes include 400 (missing/invalid parameter), 401 (missing/invalid X-API-Key), 404 (not found), 422 (parameter out of range), 429 (rate limit exceeded), and 500 (server error). Implement exponential backoff for 429/500 and validate input types client-side to avoid 400/422.
Developer notes that save time
- Authentication: always send X-API-Key: YOUR_API_KEY. There is no per-endpoint OAuth flow.
- Units and frames: distances in NM, speeds in knots, lat/lon in decimal degrees (WGS84), UTC timestamps in ISO 8601.
- History window: /vessels/track supports hours up to 168h; default is 24h.
- Pagination: /vessels/search uses page and per_page (max 100). Persist cursors in query strings for shareable links.
- Caching: key by MMSI/IMO and hours parameter. Respect timestamp_utc and add an Age header or UI hint for stale AIS when needed.
- Event feeds: /port/activity and /port/expected-arrivals can augment tug readiness scheduling alongside /vessels/track.
Additional examples
Python: find tug by name, then track
import requests
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://vessels-api.com/api/V1"
# 1) Search for tugs named "Atlantic"
s = requests.get(
f"{BASE_URL}/vessels/search",
headers={"X-API-Key": API_KEY},
params={"query": "atlantic", "ship_type": "Tug", "per_page": 5}
).json()
if not s.get("success") or not s["data"]["vessels"]:
raise SystemExit("Tug not found")
mmsi = s["data"]["vessels"][0].get("mmsi") or ""
if not mmsi:
raise SystemExit("First result missing MMSI; pick another candidate")
# 2) Track the selected tug for the last 24 hours
t = requests.get(
f"{BASE_URL}/vessels/track",
headers={"X-API-Key": API_KEY},
params={"mmsi": mmsi, "hours": 24, "include_route": "true", "include_predicted_eta": "true"}
).json()
pos = t["data"]["current_position"]
print(f"Tug MMSI {mmsi} at {pos['latitude']},{pos['longitude']} speed {pos['speed_knots']} kn at {pos['timestamp_utc']} UTC")
cURL: nearby traffic picture around a tug job site
Combine this with your tug’s own vector to plan safe approach paths during tow or berthing operations.
ESG and compliance for harbor fleets
If your tug operator reports emissions, GET /vessels/green returns IMO CII-aligned metrics for a given IMO or MMSI over a selectable period (24h, 7d, 30d, 1y). The response includes estimated_emissions and a cii rating A→E based on IMO MEPC.339(76). This integrates into internal ESG dashboards alongside operational tracking.
Why developers use this for tug operations
- Single header, single base URL. There are no per-endpoint auth differences to debug.
- Consistent response envelope. Uniform parsing for {status, success, message, data} minimizes branching.
- Global AIS coverage with near real-time refresh. Run the same codebase for different ports.
- Scales from one tug to a full harbor fleet using /vessels/fleet batching.
When you are building Transportation software—dispatch boards, pilot/tug coordination apps, or port ops consoles—you want a handful of endpoints that just work together. These five do.
FAQ
How often should I poll /vessels/track for a tug?
Polling every 30–60 seconds is common for map UIs. Use the timestamp_utc to detect unchanged data and throttle updates client-side.
What does navigational_status mean?
It is the AIS nav status integer from the live feed. Many teams treat 0/1 as underway variants and filter moored/at anchor codes to drive color states on the map.
Can I request history beyond 24 hours?
Yes. Set hours up to 168 for a 7-day window on /vessels/track.
How do I keep my fleet view efficient?
Batch with POST /vessels/fleet. Store last-seen timestamps per MMSI to avoid redrawing static markers until the AIS timestamp changes.
Which ports can I query for congestion?
Use GET /ports to browse the catalog and fetch identifiers. Then call /ports/congestion with a valid port_id like ARBUE, SGSIN, or NLRTM.
Ready to build your tug tracking and operations board? Start with the official Documentation, try live calls in the MCP, and get an API key to ship your integration: Register.

