You need to build a cruise operations dashboard that can find ships by name, follow live tracks with ETA, and alert staff when cruise vessels are sailing near key waypoints or ports. By the end of this post, you’ll know exactly how to implement cruise ship search, live tracking with history, and “nearby” proximity queries using vessels-api.com—all with a single API key, consistent JSON, and endpoints designed for transportation use cases.
Why developers use vessels-api.com for cruise tracking
vessels-api.com provides a transportation-focused AIS data service with 18 REST endpoints that cover vessel search, live tracking with history, fleet operations, port intelligence, and IMO CII emissions scoring. Every endpoint uses the same base URL and a single X-API-Key header. Responses share a predictable envelope: {status, success, message, data}. That makes it straightforward to implement cruise workflows like:
- Customer-facing cruise maps with current position and last 48–168 hours of track.
- Operations alerts when a ship enters a threshold radius of a pilot boarding station or anchorage.
- Voyage analytics (distance, speed profile, port calls) for service QA and post-voyage reviews.
- ESG/CII checks for sustainability reporting aligned with IMO MEPC.339(76).
All timestamps are UTC. Distance is in nautical miles (nm). Speed is in knots. The API supports global AIS coverage with near real-time refresh rates and offers a 7-day free trial on all plans. See the Documentation when you’re ready to extend beyond the basics in this guide.
Core cruise workflow: Search → Track → Nearby
For cruise scenarios, these three endpoints do most of the heavy lifting:
- GET /vessels/search — quickly identify the cruise ship (by name, IMO, or MMSI).
- GET /vessels/track — retrieve live position, up to 168 hours of history, route, and ETA.
- GET /vessels/nearby — find all vessels within a radius of a coordinate (e.g., port pilot station).
1) Find your cruise ship with /vessels/search
Start by locating the vessel record via fuzzy name, IMO, or MMSI. For cruise lines with sister ships on similar itineraries, filter by ship_type to narrow results.
cURL
curl -H "X-API-Key: YOUR_API_KEY" "https://vessels-api.com/api/V1/vessels/track?mmsi=258785000&hours=48"
Example JSON snippet
{
"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
}
}
What to use:
- imo and mmsi — stable identifiers to pass to tracking and analytics calls.
- vessel_type — ensure you’ve matched a passenger/cruise ship.
- pagination — respect per_page (max 100) and paginate if your query is broad.
2) Live track, history, and ETA with /vessels/track
Once you have the MMSI or IMO, request live position, up to 168 hours of history, and route details. For cruise ops, include_route and include_predicted_eta are useful when comparing scheduled vs. predicted arrival windows.
Official cURL (copy-paste):
Official JSON response (verbatim):
Fields to wire into your app:
- data.current_position.latitude/longitude — plot the live marker on your map.
- data.current_position.speed_knots and course_degrees — render directional arrows and speed badges.
- data.route.{departure_port,destination_port,eta,avg_speed_knots} — show itinerary and planned arrival.
- data.last_port_visits — context for port ops and historical call chains.
- hours parameter — set up to 168 for seven days of breadcrumbs in your track layer.
JavaScript example (fetch)
async function getCruiseTrack() {
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();
// Envelope: { status, success, message, data }
const { data } = json;
const { latitude, longitude, speed_knots, course_degrees, timestamp_utc } =
data.current_position;
console.log("Position:", latitude, longitude);
console.log("Speed (kn):", speed_knots, "Course (°):", course_degrees);
console.log("Timestamp UTC:", timestamp_utc);
if (Array.isArray(data.position_history)) {
// Draw polyline from history points if present
console.log("Breadcrumbs:", data.position_history.length);
}
if (data.route) {
const { departure_port, destination_port, eta, avg_speed_knots } = data.route;
console.log("Voyage:", departure_port, "→", destination_port);
console.log("Planned ETA:", eta, "Avg speed (kn):", avg_speed_knots);
}
}
getCruiseTrack().catch(console.error);
Practical notes
- Timestamps are UTC ISO-8601 strings; convert client-side to local port time if needed.
- History length controls payload size; cache for a few minutes to reduce map tile churn.
- When live AIS is sparse, current_position.age_minutes helps you flag stale positions.
3) Detect cruise ships near a coordinate with /vessels/nearby
Use the nearby endpoint to detect when a cruise ship is within a nautical-mile radius of a point—e.g., port limits, anchorage, pilot boarding area, or a marine park you want to protect with geofencing.
cURL
Example JSON snippet
What to use:
- data.vessels[].distance_nm — sort by closest ship for pilotage handoff.
- ship_type=Passenger — filter non-cruise vessels to reduce false positives.
- radius (default 50, max 200) — tune based on your approach channel and AIS cell size.
Optional: Voyage analytics for cruise QA with /vessels/analytics
Quantify performance across a day or week: total distance, speed profile, and port call counts. This is handy for service reliability checks, post-voyage retros, and automated notifications when a vessel’s average speed cannot meet a turnaround window.
cURL
Example JSON snippet
What to use:
- total_distance_nm — voyage distance for fuel and schedule planning.
- avg_speed_knots and max_speed_knots — speed KPIs against timetables.
- port_calls_count and total_time_in_port_hours — turnaround efficiency and berth occupancy planning.
Putting it together: a minimal cruise ops workflow
- Resolve the vessel by name or IMO using GET /vessels/search. Cache the identifiers and vessel_type.
- Pull live track and route with GET /vessels/track. Store latitude/longitude, course, and ETA in your map model. Update at a sane polling interval (e.g., 1–5 minutes based on your UI sensitivity).
- Trigger proximity checks with GET /vessels/nearby for each key waypoint. Fire alerts when distance_nm drops below your threshold.
- Compute operational KPIs with GET /vessels/analytics in batch once per day for dashboards.
Production integration details that save time
- Authentication: every request includes X-API-Key with your token. No OAuth or per-endpoint differences.
- Consistency: every response has the same envelope—always check success before consuming data.
- Units: distances in nautical miles; speed in knots; timestamps in UTC ISO-8601.
- Pagination: search uses page and per_page (max 100). Handle last_page to prevent overfetching.
- Polling and caching: throttle track polls to your UX. Cache “nearby” lookups for 30–60 seconds to reduce chatter while preserving responsiveness.
- Error handling: 400 (bad params), 401 (auth), 404 (not found), 422 (out of range), 429 (rate limit), 500 (server). Back off and retry with jitter on 429/500.
- Data freshness: check age_minutes in current_position to identify stale AIS and gray out markers.
Bonus for cruise ESG teams: /vessels/green (CII)
For emissions tracking aligned with IMO MEPC.339(76), use /vessels/green to fetch CII scores and estimated CO2. This is useful for cruise ESG dashboards and compliance monitoring.
cURL
Example JSON snippet
Key fields:
- estimated_emissions.co2_tons and co2_per_nm — basis for trend charts and voyage baselines.
- cii.rating — A (best) through E (worst) for at-a-glance compliance status.
End-to-end example: map + nearby alert
Workflow
- Use /vessels/search to let an operator pick the correct cruise ship by name.
- Start a 60s poll of /vessels/track to keep the live marker updated.
- Every 2 minutes, call /vessels/nearby for the pilot station coordinate with ship_type=Passenger. If a ship’s distance_nm ≤ 5 nm and speed_knots ≥ 10 kn, trigger an early pilot dispatch alert.
JavaScript sketch
const API_KEY = "YOUR_API_KEY";
const BASE = "https://vessels-api.com/api/V1";
async function trackAndAlert(mmsi, pilotLat, pilotLon) {
// 1) Track
const trackRes = await fetch(`${BASE}/vessels/track?mmsi=${mmsi}&hours=24`, {
headers: { "X-API-Key": API_KEY }
});
const trackJson = await trackRes.json();
if (!trackJson.success) throw new Error(trackJson.message);
const pos = trackJson.data.current_position;
plotMarker(pos.latitude, pos.longitude, {
course: pos.course_degrees,
speed: pos.speed_knots,
updatedAt: pos.timestamp_utc
});
// 2) Nearby check at pilot station
const nearUrl =
`${BASE}/vessels/nearby?latitude=${pilotLat}&longitude=${pilotLon}` +
`&radius=10&ship_type=Passenger&limit=50`;
const nearRes = await fetch(nearUrl, { headers: { "X-API-Key": API_KEY } });
const nearJson = await nearRes.json();
if (nearJson.success) {
const candidates = nearJson.data.vessels
.filter(v => Number(v.speed_knots) >= 10 && Number(v.distance_nm) <= 5);
if (candidates.length > 0) {
notifyPilotDispatch(candidates.map(v => ({
name: v.name,
mmsi: v.mmsi,
distanceNm: v.distance_nm,
speedKn: v.speed_knots
})));
}
}
}
This pattern generalizes to multiple waypoints (e.g., harbor entrance, anchorage, berth approach) and multiple vessels in a fleet view.
Development tooling and fleet scaling
- Batch operations: use POST /vessels/fleet to fetch positions and routes for multiple cruise ships in one call. This reduces round-trips for dashboard overviews.
- Port context: when you need a port list for itinerary planning, GET /ports returns 248 ports with coordinates and timezone—handy for map jump menus.
- Event feeds: if your ops team needs arrivals/departures for excursions and provisioning, use GET /port/activity and GET /port/expected-arrivals as complementary signals to /vessels/track.
FAQ
Q: What’s the authentication flow?
A: Send your key in the X-API-Key header on every request. There is no OAuth or per-endpoint variation.
Q: What time standard do timestamps use?
A: All timestamps are UTC ISO-8601. Convert to local timezones on the client using the port’s timezone from GET /ports if you need local displays.
Q: How often should I poll /vessels/track?
A: For cruise UIs, 30–120 seconds is typical. Use age_minutes to handle stale updates and cache responses to throttle redraws.
Q: Can I filter nearby to only cruise ships?
A: Yes. Pass ship_type=Passenger to GET /vessels/nearby to narrow to cruise vessels and ferries classified under passenger ship types.
Q: How do I handle large search results?
A: Use page and per_page (max 100). Read pagination.last_page to stop fetching when completed.
Next steps
Use the official track example above to get your first cruise marker on a map. Then add nearby alerts for your port waypoints and wire the route ETA into your turnaround board. When you’re ready to expand to fleet operations and port intelligence, explore the full set of endpoints in the Documentation, run test calls in the MCP, and get your key via Register.




