VesselTrack

REST API

VesselTrack API Documentation

Query live AIS positions, normalized destinations, vessel history, tracks, watchlists, alerts, and subscription state. Use the canonical `www` host or pass `-L` to cURL because the apex domain redirects.

Authentication

External integrations should use an active-plan API key. A key authenticates as the owning user, so account, billing, watchlist, and alert endpoints accept it as well as the public data endpoints.

X-API-Key: vt_live_...
Authorization: Bearer vt_live_...

API-key requests are metered. Default plan limit: 3,600 requests/hour; admin keys: 20,000 requests/hour.

Timestamps are UTC in API responses. The UI displays UTC and the user's local timezone.

GET/api/statsPublic

Global Stats

High-level vessel counts for the public dashboard.

curl -L https://www.vesseltrack.net/api/stats
{ "total_vessels": 90000, "updated_last_1h": 12000, "updated_last_24h": 60000 }
GET/api/vessels/mapPublic

Map Vessel Positions

Lightweight map payload. The web app paints a bounded initial payload for speed and exposes a manual full-fleet load when needed.

Query / Path
ship_typecsv<number>AIS ship type codes, for example 70,80.
nav_statuscsv<number>AIS navigation status codes.
sog_min / sog_maxnumberSpeed-over-ground bounds in knots.
has_name1Only return named vessels.
stale_minutesnumberOnly vessels updated within this many minutes.
destinationstringRaw destination text search.
destination_port / dest_portscsv<UN/LOCODE>Normalized port codes such as NZTRG or SGSIN.
destination_country / dest_countriescsv<string>Country name or ISO prefix such as New Zealand or NZ.
destination_citycsv<string>Normalized or raw destination city search.
flagcsv<MID>MMSI MID prefixes, for example 338,366.
limit / offsetnumberPagination. `/api/vessels` defaults to 500 and caps at 10,000.
limitnumberOptional cap, max 100,000. Omit to return all matching positioned vessels.
show_unknownbooleanSet to 1 to include vessels without a known AIS ship type. Defaults off for faster map loads.
curl -L "https://www.vesseltrack.net/api/vessels/map?limit=1000"
{ "count": 88722, "freshness": { "mode": "fresh" }, "vessels": [{ "mmsi": 566000000, "lat": -37.6, "lon": 176.1, "heading": 511, "ship_type": 80, "sog": 0, "name": "HAFNIA FALCON" }] }
GET/api/vesselsSite session or API key

List Vessels

Full translated vessel records with normalized destination metadata and filtering.

Query / Path
ship_typecsv<number>AIS ship type codes, for example 70,80.
ship_categorycsv<string>High-level categories such as cargo, tanker, passenger, tug, fishing.
nav_statuscsv<number>AIS navigation status codes.
sog_min / sog_maxnumberSpeed-over-ground bounds in knots.
has_name1Only return named vessels.
stale_minutesnumberOnly vessels updated within this many minutes.
destinationstringRaw destination text search.
destination_port / dest_portscsv<UN/LOCODE>Normalized port codes such as NZTRG or SGSIN.
destination_country / dest_countriescsv<string>Country name or ISO prefix such as New Zealand or NZ.
destination_citycsv<string>Normalized or raw destination city search.
flagcsv<MID>MMSI MID prefixes, for example 338,366.
updated_since / updated_beforeISO datetimePosition update window. Datetimes are interpreted as UTC.
limit / offsetnumberPagination. `/api/vessels` defaults to 500 and caps at 10,000.
curl -L -H "X-API-Key: vt_live_..." "https://www.vesseltrack.net/api/vessels?limit=100&ship_category=tanker&destination_country=NZ"
{ "count": 100, "total": 88722, "limit": 100, "offset": 0, "vessels": [{ "identity": {}, "navigation": {}, "destination_normalized": {} }] }
GET/api/vessels/searchPublic

Search Vessels

Search by MMSI, IMO, vessel name, callsign, or destination.

Query / Path
q*stringMinimum 2 characters.
limitnumberDefault 50, max 200.
curl -L -H "X-API-Key: vt_live_..." "https://www.vesseltrack.net/api/vessels/search?q=HAFNIA%20FALCON"
{ "count": 3, "query": "HAFNIA", "vessels": [{ "identity": { "mmsi": 566000000, "name": "HAFNIA FALCON" } }] }
GET/api/vessels/{identifier}Site session or API key

Vessel Detail

Full translated detail for one vessel. Seven-digit identifiers resolve as IMO first; MMSI is the fallback.

Query / Path
identifier*numberIMO preferred when available, otherwise MMSI.
curl -L -H "X-API-Key: vt_live_..." https://www.vesseltrack.net/api/vessels/9043940
{ "vessel": { "identity": {}, "navigation": {}, "timestamps": {} }, "lookup": { "canonicalType": "imo" } }
GET/api/vessels/{identifier}/trackActive plan API key

Vessel Track Points

Historical position points for a vessel. IMO is preferred when available; MMSI is the fallback. Paid access is enforced by API key or active site session.

Query / Path
hoursnumberLookback window, default 24.
limitnumberDefault 500.
{ "mmsi": 512345678, "imo": 9043940, "track": [{ "lat": -37.6, "lon": 176.1, "timestamp": "2026-05-27T00:00:00Z" }], "count": 1 }
GET/api/vessels/{identifier}/historyActive plan API key

Vessel Change History

Historical field changes for a single vessel, including admin and AIS-observed changes. IMO is preferred when available; MMSI is the fallback.

Query / Path
fieldstringOptional field filter.
since / untilISO datetimeUTC time window.
limitnumberMaximum events.
{ "history": [{ "field_name": "destination", "old_value": "NZMAP", "new_value": "NZTRG", "observed_at": "2026-05-27T00:00:00Z" }], "count": 1 }
GET/api/vessels/{identifier}/eventsActive plan API key

Vessel Event Timeline

Derived event feed for a vessel, including future port-call and voyage events.

Query / Path
event_typestringOptional event type filter.
since / untilISO datetimeUTC time window.
limit / offsetnumberPagination.
{ "events": [{ "event_type": "arrival", "title": "Arrived Tauranga", "observed_at": "2026-05-27T00:00:00Z" }], "count": 1 }
GET/api/vessels/{identifier}/port-callsActive plan API key

Vessel Port Calls

Port-call ledger for a vessel, keyed by IMO first and MMSI second.

Query / Path
event_typestringarrival, departure, in_port, anchorage, berth, or expected_arrival.
limit / offsetnumberPagination.
{ "port_calls": [{ "port_locode": "NZTRG", "event_type": "arrival", "observed_at": "2026-05-27T00:00:00Z" }], "count": 1 }
GET/api/vessels/{mmsi}/enrichSite session or API key

Vessel Enrichment

Vessel photo from a licensed Wikimedia Commons lookup (cached 7 days) plus deep links to external maritime references. Keyed by MMSI.

Query / Path
mmsi*numberVessel MMSI (path parameter).
{ "mmsi": 566000000, "imageUrl": "https://upload.wikimedia.org/...", "imageSource": "wikimedia", "wikiUrl": "https://commons.wikimedia.org/...", "cached": true, "externalLinks": [{ "name": "MarineTraffic", "url": "https://..." }] }
GET/api/vessels/historyActive plan API key

Fleet Change History

Fleet-wide vessel field-change feed.

Query / Path
mmsinumberOptional MMSI.
fieldstringOptional field filter.
since / untilISO datetimeUTC time window.
limitnumberMaximum events.
{ "history": [], "count": 0 }
GET/api/vessels/destinationsSite session or API key

Destination Taxonomy

Supported countries, ports, and optional live vessel counts for normalized destination filters.

Query / Path
countsbooleanSet true to include current counts.
{ "countries": [{ "country": "New Zealand", "ports": [] }], "count": 1 }
GET/api/portsPublic

List Ports

Canonical port search backed by the local ports table. Import UN/LOCODE using `scripts/import-ports.mjs`.

Query / Path
qstringSearch port code, name, city, or approved alias.
country_codeISO 3166-1 alpha-2Filter by country code, for example NZ.
locodeUN/LOCODEExact port code.
limit / offsetnumberPagination. Default 100, max 1,000.
{ "ports": [{ "locode": "NZTRG", "name": "Tauranga", "inbound_vessels": 12 }], "count": 1 }
GET/api/ports/{locode}Site session or API key

Port Detail

Canonical port detail with aliases and current activity counters.

{ "port": { "locode": "NZTRG", "name": "Tauranga", "alias_count": 4 }, "aliases": [] }
GET/api/ports/{locode}/vesselsSite session or API key

Port Destination Vessels

Current vessels reporting a normalized destination port.

Query / Path
statusstring`inbound` or `recent`.
limit / offsetnumberPagination. Default 500, max 5,000.
{ "port": "NZTRG", "vessels": [{ "identity": {}, "destination": {} }], "count": 1 }
GET/api/ports/{locode}/port-callsSite session or API key

Port Call Ledger

Recent port-call events for a port. Public/site access is capped to 7 days; active plans can request up to 366 days.

Query / Path
event_typestringarrival, departure, in_port, anchorage, berth, or expected_arrival.
daysnumberLookback window. Public max 7, plan max 366.
limit / offsetnumberPagination.
{ "port_calls": [{ "mmsi": 512345678, "port_locode": "NZTRG", "event_type": "arrival" }], "count": 1 }
GET/api/watchlistLogged-in user

List Watchlist

Returns the current user watchlist. API-key requests are tied to the owning user.

{ "watchlist": [] }
POST/api/watchlistLogged-in user

Add Watchlist Entry

Adds a vessel to the current user watchlist. Alert notification settings require an active plan.

Body
mmsi*numberVessel MMSI.
labelstringOptional custom label.
notifyOnarray<string>Alert fields such as destination_change or nav_status_change.
{ "item": { "id": 1, "mmsi": 566000000 } }
PUT/api/watchlistLogged-in user

Update Watchlist Entry

Updates label and alert configuration for one watchlist entry.

Body
id*numberWatchlist entry id.
notifyOnarray<string>Alert fields.
speedThreshold / headingChangeDeg / aisGapMinutesnumberOptional thresholds.
{ "message": "Updated" }
DELETE/api/watchlist?id={id}Logged-in user

Remove Watchlist Entry

Deletes one watchlist entry owned by the current user.

{ "message": "Removed" }
GET/api/watchlist/alertsLogged-in user

List Watchlist Alerts

Returns recent watchlist alerts for the current user.

{ "alerts": [] }
PUT/api/watchlist/alertsLogged-in user

Acknowledge Alerts

Acknowledges selected alerts or all current alerts.

Body
alertIdsarray<number>Specific alerts.
acknowledgeAllbooleanAcknowledge all unacknowledged alerts.
{ "message": "Acknowledged" }
GET/api/accountLogged-in user

Account Profile

Returns current user profile, subscription, and API-key preview.

{ "user": { "email": "user@example.com", "subscription_status": "active", "api_key_preview": "vt_live_..." } }
POST/api/accountLogged-in user

Regenerate API Key

Issues a new one-time API key for active-plan users.

Body
action*"regenerate-api-key"Required action string.
{ "api_key": "vt_live_...", "api_key_preview": "vt_live_abc..." }
PUT/api/accountLogged-in user

Update Account

Updates profile name fields or password.

Body
firstName / lastNamestringProfile fields.
currentPassword / newPasswordstringPassword change fields.
{ "message": "Updated successfully" }
GET/api/account/alertsLogged-in user

Email Alert Preferences

Gets email alert preferences.

{ "emailAlertsEnabled": true, "emailAlertTypes": [] }
PUT/api/account/alertsLogged-in user

Update Email Alert Preferences

Updates email alert preferences. Active plan required when enabling alert types.

Body
emailAlertsEnabledbooleanEnable email alerts.
emailAlertTypesarray<string>Selected alert types.
alertConfigsobjectThreshold values.
{ "message": "Alert preferences updated" }
GET/api/stripe/statusLogged-in user

Subscription Status

Returns current user billing/access state.

{ "subscriptionStatus": "active", "hasApiAccess": true, "hasApiKey": true }
POST/api/stripe/checkoutLogged-in user

Create Checkout Session

Starts checkout for VesselTrack Pro at $17 USD/month.

{ "url": "https://checkout.stripe.com/..." }
GET/api/stripe/checkoutLogged-in user

Create Billing Portal Session

Returns a Stripe billing portal URL for existing customers.

{ "url": "https://billing.stripe.com/..." }
GET/api/stripe/invoicesLogged-in user

Invoices

Returns recent Stripe invoices for the current customer. Amounts are displayed as USD in the UI.

{ "invoices": [{ "amount_paid": 1700, "currency": "usd" }] }
POST/api/stripe/confirmLogged-in user

Confirm Checkout

Synchronizes one completed Checkout session after redirect.

Body
checkoutSessionId*stringStripe Checkout session id.
{ "subscriptionStatus": "active" }
POST/api/stripe/webhookStripe webhook

Stripe Webhook

Stripe-signed webhook endpoint for subscription and invoice lifecycle events.

{ "received": true }
POST/api/auth/registerPublic auth flow

Register

Creates a user and sends an email verification link.

Body
email*stringUser email.
password*stringMinimum 8 characters.
{ "message": "Account created. Please check your email to verify your address." }
GET/api/auth/verify?token={token}Public auth flow

Verify Email

Verifies a registration email token and sends a welcome email.

Redirects to /login?verify=success or an error state.
POST/api/auth/verification/resendPublic auth flow

Resend Verification

Sends a fresh verification link for an unverified account without revealing whether the account exists.

Body
email*stringUser email.
{ "message": "If that email is unverified, a verification link has been sent." }
POST/api/auth/password-reset/requestPublic auth flow

Request Password Reset

Creates a 1-hour password reset token and emails it through Resend without account enumeration.

Body
email*stringUser email.
{ "message": "If that email exists, a reset link has been sent." }
POST/api/auth/password-reset/confirmPublic auth flow

Confirm Password Reset

Sets a new password from a valid reset token.

Body
token*stringReset token from email.
password*stringMinimum 8 characters.
{ "message": "Password reset successfully" }
GET/POST/api/auth/[...nextauth]Public auth flow

NextAuth

NextAuth session, CSRF, and credentials callback routes.

Managed by NextAuth.
GET/api/admin/*Admin session

Admin Routes

Admin-only users, vessels, activity, and stats endpoints. These are not external API products.

Admin JSON responses.