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.
/api/statsPublicGlobal 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 }/api/vessels/mapPublicMap Vessel Positions
Lightweight map payload. The web app paints a bounded initial payload for speed and exposes a manual full-fleet load when needed.
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" }] }/api/vesselsSite session or API keyList Vessels
Full translated vessel records with normalized destination metadata and filtering.
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": {} }] }/api/vessels/searchPublicSearch Vessels
Search by MMSI, IMO, vessel name, callsign, or destination.
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" } }] }/api/vessels/{identifier}Site session or API keyVessel Detail
Full translated detail for one vessel. Seven-digit identifiers resolve as IMO first; MMSI is the fallback.
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" } }/api/vessels/{identifier}/trackActive plan API keyVessel 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.
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 }/api/vessels/{identifier}/historyActive plan API keyVessel Change History
Historical field changes for a single vessel, including admin and AIS-observed changes. IMO is preferred when available; MMSI is the fallback.
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 }/api/vessels/{identifier}/eventsActive plan API keyVessel Event Timeline
Derived event feed for a vessel, including future port-call and voyage events.
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 }/api/vessels/{identifier}/port-callsActive plan API keyVessel Port Calls
Port-call ledger for a vessel, keyed by IMO first and MMSI second.
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 }/api/vessels/{mmsi}/enrichSite session or API keyVessel Enrichment
Vessel photo from a licensed Wikimedia Commons lookup (cached 7 days) plus deep links to external maritime references. Keyed by MMSI.
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://..." }] }/api/vessels/historyActive plan API keyFleet Change History
Fleet-wide vessel field-change feed.
mmsinumberOptional MMSI.fieldstringOptional field filter.since / untilISO datetimeUTC time window.limitnumberMaximum events.{ "history": [], "count": 0 }/api/vessels/destinationsSite session or API keyDestination Taxonomy
Supported countries, ports, and optional live vessel counts for normalized destination filters.
countsbooleanSet true to include current counts.{ "countries": [{ "country": "New Zealand", "ports": [] }], "count": 1 }/api/portsPublicList Ports
Canonical port search backed by the local ports table. Import UN/LOCODE using `scripts/import-ports.mjs`.
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 }/api/ports/{locode}Site session or API keyPort Detail
Canonical port detail with aliases and current activity counters.
{ "port": { "locode": "NZTRG", "name": "Tauranga", "alias_count": 4 }, "aliases": [] }/api/ports/{locode}/vesselsSite session or API keyPort Destination Vessels
Current vessels reporting a normalized destination port.
statusstring`inbound` or `recent`.limit / offsetnumberPagination. Default 500, max 5,000.{ "port": "NZTRG", "vessels": [{ "identity": {}, "destination": {} }], "count": 1 }/api/ports/{locode}/port-callsSite session or API keyPort 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.
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 }/api/watchlistLogged-in userList Watchlist
Returns the current user watchlist. API-key requests are tied to the owning user.
{ "watchlist": [] }/api/watchlistLogged-in userAdd Watchlist Entry
Adds a vessel to the current user watchlist. Alert notification settings require an active plan.
mmsi*numberVessel MMSI.labelstringOptional custom label.notifyOnarray<string>Alert fields such as destination_change or nav_status_change.{ "item": { "id": 1, "mmsi": 566000000 } }/api/watchlistLogged-in userUpdate Watchlist Entry
Updates label and alert configuration for one watchlist entry.
id*numberWatchlist entry id.notifyOnarray<string>Alert fields.speedThreshold / headingChangeDeg / aisGapMinutesnumberOptional thresholds.{ "message": "Updated" }/api/watchlist?id={id}Logged-in userRemove Watchlist Entry
Deletes one watchlist entry owned by the current user.
{ "message": "Removed" }/api/watchlist/alertsLogged-in userList Watchlist Alerts
Returns recent watchlist alerts for the current user.
{ "alerts": [] }/api/watchlist/alertsLogged-in userAcknowledge Alerts
Acknowledges selected alerts or all current alerts.
alertIdsarray<number>Specific alerts.acknowledgeAllbooleanAcknowledge all unacknowledged alerts.{ "message": "Acknowledged" }/api/accountLogged-in userAccount Profile
Returns current user profile, subscription, and API-key preview.
{ "user": { "email": "user@example.com", "subscription_status": "active", "api_key_preview": "vt_live_..." } }/api/accountLogged-in userRegenerate API Key
Issues a new one-time API key for active-plan users.
action*"regenerate-api-key"Required action string.{ "api_key": "vt_live_...", "api_key_preview": "vt_live_abc..." }/api/accountLogged-in userUpdate Account
Updates profile name fields or password.
firstName / lastNamestringProfile fields.currentPassword / newPasswordstringPassword change fields.{ "message": "Updated successfully" }/api/account/alertsLogged-in userEmail Alert Preferences
Gets email alert preferences.
{ "emailAlertsEnabled": true, "emailAlertTypes": [] }/api/account/alertsLogged-in userUpdate Email Alert Preferences
Updates email alert preferences. Active plan required when enabling alert types.
emailAlertsEnabledbooleanEnable email alerts.emailAlertTypesarray<string>Selected alert types.alertConfigsobjectThreshold values.{ "message": "Alert preferences updated" }/api/stripe/statusLogged-in userSubscription Status
Returns current user billing/access state.
{ "subscriptionStatus": "active", "hasApiAccess": true, "hasApiKey": true }/api/stripe/checkoutLogged-in userCreate Checkout Session
Starts checkout for VesselTrack Pro at $17 USD/month.
{ "url": "https://checkout.stripe.com/..." }/api/stripe/checkoutLogged-in userCreate Billing Portal Session
Returns a Stripe billing portal URL for existing customers.
{ "url": "https://billing.stripe.com/..." }/api/stripe/invoicesLogged-in userInvoices
Returns recent Stripe invoices for the current customer. Amounts are displayed as USD in the UI.
{ "invoices": [{ "amount_paid": 1700, "currency": "usd" }] }/api/stripe/confirmLogged-in userConfirm Checkout
Synchronizes one completed Checkout session after redirect.
checkoutSessionId*stringStripe Checkout session id.{ "subscriptionStatus": "active" }/api/stripe/webhookStripe webhookStripe Webhook
Stripe-signed webhook endpoint for subscription and invoice lifecycle events.
{ "received": true }/api/auth/registerPublic auth flowRegister
Creates a user and sends an email verification link.
email*stringUser email.password*stringMinimum 8 characters.{ "message": "Account created. Please check your email to verify your address." }/api/auth/verify?token={token}Public auth flowVerify Email
Verifies a registration email token and sends a welcome email.
Redirects to /login?verify=success or an error state./api/auth/verification/resendPublic auth flowResend Verification
Sends a fresh verification link for an unverified account without revealing whether the account exists.
email*stringUser email.{ "message": "If that email is unverified, a verification link has been sent." }/api/auth/password-reset/requestPublic auth flowRequest Password Reset
Creates a 1-hour password reset token and emails it through Resend without account enumeration.
email*stringUser email.{ "message": "If that email exists, a reset link has been sent." }/api/auth/password-reset/confirmPublic auth flowConfirm Password Reset
Sets a new password from a valid reset token.
token*stringReset token from email.password*stringMinimum 8 characters.{ "message": "Password reset successfully" }/api/auth/[...nextauth]Public auth flowNextAuth
NextAuth session, CSRF, and credentials callback routes.
Managed by NextAuth./api/admin/*Admin sessionAdmin Routes
Admin-only users, vessels, activity, and stats endpoints. These are not external API products.
Admin JSON responses.