Solutions · Vessels API

Live ship positions, tracks and area alerts

Query every vessel reporting in an area, look one up by MMSI, replay its track with the sea state along the way, and get a webhook the moment a ship enters or leaves the waters you care about.

  • Terminal and pilot planning
  • Security and exclusion-zone monitoring
  • Offshore asset proximity alerts
Request
# Vessels by bbox or point + radius_nm, filtered by type, status or name q
curl "https://www.seasignals.com/v1/vessels?bbox=3.5,51.5,4.5,52.2&type=cargo" \
  -H "Authorization: Bearer $SS_KEY"
Endpoints

Query it whenever you need it

GeoJSON responses with typed IDs, ISO 8601 times and units in every field name. Errors come back as {"error": {"code", "message"}}.

GET/v1/vesselsVessels by bbox or point + radius_nm, filtered by type, status or name q
GET/v1/vessels/{mmsi}One vessel: identity, position, speed, course, destination and current port
GET/v1/vessels/{mmsi}/trackTrack between from and to, with join=waves for sea state along the way
Webhooks

Or let the events come to you

Subscribe a URL once and SeaSignals POSTs a signed JSON event whenever something changes. Checked every 5 minutes.

EVENTvessel.entered_areaA vessel matching your filters started reporting inside your bbox
EVENTvessel.left_areaIt left the bbox, or stopped reporting for an hour

Filters

bboxRequired. [west, south, east, north], at most 20° per side
typesVessel types, e.g. ["cargo", "tanker"]
mmsiOnly these vessels
Create a webhook
curl -X POST https://www.seasignals.com/v1/webhooks \
  -H "Authorization: Bearer $SS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://example.com/hooks/seasignals",
  "product": "vessels",
  "events": [
    "vessel.entered_area",
    "vessel.left_area"
  ],
  "filters": {
    "bbox": [
      3.5,
      51.5,
      4.5,
      52.2
    ],
    "types": [
      "cargo",
      "tanker"
    ]
  }
}'
POST to your URL
{
  "id": "evt_3kV9q2mXw8rT1yLp0aZc4nB7",
  "type": "vessel.entered_area",
  "created_at": "2026-10-29T09:00:12Z",
  "webhook": "webhook:42",
  "data": {
    "type": "Feature",
    "id": "vessel:mmsi:244123456",
    "geometry": {
      "type": "Point",
      "coordinates": [
        3.82,
        51.97
      ]
    },
    "properties": {
      "name": "NORDIC STAR",
      "type": "cargo",
      "sog_kn": 11.2,
      "cog_deg": 84.0,
      "destination": "NL RTM",
      "position_time": "2026-10-29T08:41:12Z"
    }
  }
}
Delivery

Signed, retried, logged

  • Signed: every request carries SeaSignals-Signature, an HMAC-SHA256 of the timestamp and body with your webhook secret.
  • Retried: anything but a 2xx within 10 seconds is retried after 1 min, 5 min, 30 min, 2 h and 6 h.
  • Logged: GET /v1/webhooks/{id} shows recent deliveries, and POST /v1/webhooks/{id}/test sends a test event.
  • Safe to retry: use the event id to ignore a delivery you've already handled.
// header: SeaSignals-Signature: t=1761729600,v1=5f2b…
const [t, v1] = header.split(",").map((p) => p.split("=")[1]);
const expected = crypto.createHmac("sha256", process.env.SS_WEBHOOK_SECRET)
  .update(`${t}.${rawBody}`).digest("hex");
const ok = crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected))
  && Date.now() / 1000 - Number(t) < 300;

Try the Vessels API free

The free trial includes every API and up to 5 webhooks, 1,000 requests a day and 14 days of history.