API

All fleet and event data is also available as an open, unauthenticated JSON API — no account, no API key needed. Meant for your own automations (Home Assistant, n8n, Node-RED, custom scripts). To prevent abuse, a rate limit of 60 requests/minute per IP address applies; the response includes the headers X-RateLimit-Limit and X-RateLimit-Remaining for this, and 429 with Retry-After when exceeded.

GET /api/v1/ships

Current status of all 8 fleet ships.

curl https://schiffstracker.example.de/api/v1/ships
[
  {
    "mmsi": "477116800",
    "slug": "hefei",
    "name": "BYD Hefei",
    "latitude": 53.55,
    "longitude": 8.58,
    "sog": 15.2,
    "cog": 41,
    "destination_name": "Hamburg",
    "destination_confidence": "gesichert",
    "heading_to_germany": 1,
    "eta": "2026-08-27T06:00:00.000Z",
    "position_updated_at": "2026-08-25T20:04:00.000Z",
    "...": "weitere Felder, siehe /api/v1/ships/{slug}"
  }
]

GET /api/v1/ships/{slug}

Status of a single ship. The slugs match the ship page URLs (e.g. hefei for /schiff/hefei). Unknown slug → 404.

curl https://schiffstracker.example.de/api/v1/ships/hefei
{
  "mmsi": "477116800",
  "slug": "hefei",
  "name": "BYD Hefei",
  "latitude": 53.55,
  "longitude": 8.58,
  "sog": 15.2,
  "cog": 41,
  "destination_name": "Hamburg",
  "destination_confidence": "gesichert",
  "heading_to_germany": 1,
  "eta": "2026-08-27T06:00:00.000Z",
  "position_updated_at": "2026-08-25T20:04:00.000Z",
  "approach": {
    "state": "approaching",
    "closingKm": 180.4,
    "windowHours": 22.5,
    "nearestPort": { "locode": "DEHAM", "name": "Hamburg", "distanceKm": 210.1 }
  }
}

The eta field is the estimated time of arrival as reported by the crew via AIS (ISO timestamp in UTC, or null). It is not validated and often not reset after arrival.

The approach field is a movement-based direction estimate from the track (independent of the reported destination): state is approaching, receding, steady, or unknown; closingKm is the net approach to the nearest German port within the time window. It's also included per ship in GET /api/v1/ships.

The projection field is the projected route to the German destination port (or null): kind is to-port, points are [lat, lng] pairs from the current position to the port. A ship's current heading is available separately in the cog field (course over ground).

GET /api/v1/ships/{slug}/track

The recorded track of a ship (thinned-out position points, oldest first). Optional query parameter sinceHours (default 72, maximum 720 = 30 days retention).

curl "https://schiffstracker.example.de/api/v1/ships/hefei/track?sinceHours=48"
[
  {
    "id": 1024,
    "mmsi": "477116800",
    "latitude": 51.9,
    "longitude": 4.1,
    "sog": 12.4,
    "cog": 88,
    "recorded_at": "2026-08-25T18:02:00.000Z"
  }
]

GET /api/v1/events

Events for ships heading to Germany and arriving in German ports (the same ones as in the RSS feed; for a confirmed destination and on arrival also as a Discord notification), as JSON instead of XML.

Optional query parameters: limit (default 30, max 100), mmsi (filter to one ship) and type (filter to one event type).

Event types in the event_type field: heading_to_germany_possible (possible destination in Germany, unconfirmed), heading_to_germany (confirmed destination in Germany) and arrived (arrived at the German destination port, i.e. moored, at anchor or nearly stopped).

curl "https://schiffstracker.example.de/api/v1/events?limit=10&mmsi=477116800"
curl "https://schiffstracker.example.de/api/v1/events?type=arrived"
[
  {
    "id": 42,
    "mmsi": "477116800",
    "ship_name": "BYD Hefei",
    "ship_slug": "hefei",
    "event_type": "heading_to_germany",
    "destination_name": "Hamburg",
    "occurred_at": "2026-08-25T20:04:00.000Z"
  }
]

Example: Home Assistant

“Notify me on arrival”: a REST sensor polls the latest arrived event, its value is the event id. When it changes, a ship has arrived and the automation says so. The condition stops a notification when Home Assistant restarts. Use type=heading_to_germany instead of arrived for “heading to Germany”.

# configuration.yaml
rest:
  - resource: https://schiffstracker.example.de/api/v1/events?type=arrived&limit=1
    scan_interval: 300
    sensor:
      - name: "BYD letzte Ankunft"
        value_template: "{{ value_json[0].id if value_json | length > 0 else 0 }}"
        json_attributes_path: "$[0]"
        json_attributes:
          - ship_name
          - destination_name
          - occurred_at
# automations.yaml
- alias: "BYD-Schiff angekommen"
  trigger:
    - platform: state
      entity_id: sensor.byd_letzte_ankunft
  condition:
    - condition: template
      value_template: "{{ trigger.from_state.state not in ['unknown', 'unavailable'] }}"
  action:
    - service: notify.notify
      data:
        message: >-
          {{ state_attr('sensor.byd_letzte_ankunft', 'ship_name') }} ist in
          {{ state_attr('sensor.byd_letzte_ankunft', 'destination_name') }} angekommen
Status unknown
Made with ❤️ by Softwareschmiede Lerch
v1.4.3
Changelog
  • v1.4.3 — 2026-10-22

    • Technical maintenance: internal improvements to stability and operations
  • v1.4.2 — 2026-10-22

    • Technical maintenance: minor behind-the-scenes improvements
  • v1.4.1 — 2026-10-21

    • More of the ships' destination entries are recognised and shown readably instead of just as a code, e.g. the Suez Canal transit, Khor Fakkan (UAE), Port Said and Singapore
  • v1.4.0 — 2026-10-15

    • Arrival countdown: the box at the top now shows, in large type, how many hours or days until the ship arrives according to its ETA
    • The app can now be installed on the home screen, with its own icon and launch screen (on iPhone and iPad too)
    • API docs: Home Assistant example (“notify me on arrival”)
  • v1.3.1 — 2026-10-15

    • An ETA that has already passed is no longer shown and no longer included in the Discord post – crews often leave it unchanged after arrival or a delay
    • Destinations written like “CN NBG=>SG SIN” (arrow separator, space inside the port code) are now recognised
  • v1.3.0 — 2026-10-11

    • Estimated time of arrival (ETA): when the crew reports one, it now appears for each ship, in the box at the top, in link previews and in the Discord post
    • Arrivals are recorded: when a ship with a confirmed destination reaches its German port, there is a Discord post and an entry in the RSS feed
    • New “Arrivals” page listing every recorded arrival, with the latest ones on the homepage as well. Arrivals from the last 30 days are filled in from the stored voyage data
    • Public API: new eta field for ships, new event type arrived and a type filter for events
  • v1.2.0 — 2026-10-11

    • Shared ship links now show their own preview with the ship's name, status and destination, e.g. in Discord, WhatsApp or Signal, instead of just the general logo
    • The Discord post for a ship heading to Germany now comes as a clear card with destination, position and speed
  • v1.1.3 — 2026-10-10

    • Maintenance: minor behind-the-scenes improvements
  • v1.1.2 — 2026-10-10

    • Maintenance: internal improvements to stability and operations
  • v1.1.1 — 2026-10-10

    • The site now dresses up for certain times of the year, with a seasonal note in the header – try dropping by in December
    • A few small surprises tucked away for attentive visitors – we are not saying more than that
    • The map no longer jumps back to the selected ship on every live update while you have panned it somewhere else
  • v1.1.0 — 2026-10-10

    • Push notifications via ntfy.sh have been removed. Notifications now go out exclusively via Discord, as soon as a ship with a confirmed destination sets course for Germany. The event also still appears in the public JSON API and the RSS feed
    • The Discord link now comes before the API link in the footer
  • v1.0.6 — 2026-09-26

    • A ship already anchored or moored at its German destination now shows as "arrived" instead of still "heading to Germany"
  • v1.0.5 — 2026-09-24

    • A reported destination with a space between the country and location code (e.g. "DE WVN" for Wilhelmshaven) wasn't recognized as a German destination — at least one real case went unnoticed as a result. Fixed
  • v1.0.4 — 2026-09-23

    • Technical maintenance: a more robust connection to the live data source, so stale positions are detected and recovered from automatically, faster
  • v1.0.3 — 2026-09-18

    • The disclaimer box was accidentally showing twice on the homepage — now it only appears once, in the footer
  • v1.0.2 — 2026-09-18

    • Fleet list: destination and time now sit on their own line under the ship name instead of sharing one — long destination names used to get cut off there
    • Fleet list: a reported destination now carries a small "Destination" label so it's clear what it is
  • v1.0.1 — 2026-09-18

    • The homepage now answers the actual question right at the top: is a ship heading to Germany right now — and if not, when one last was
    • The map is much larger now, with the remaining ships as a compact, neatly aligned list beside it instead of eight equally sized tiles below
    • Red is now reserved exclusively for that one signal — links, buttons and selection highlights are blue or neutral instead
    • Selecting a ship now scrolls the map to the center of the screen instead of flush under the header
  • v0.6.2 — 2026-09-17

    • The page now updates itself in the background instead of doing a full reload — your map view and selected ship stay as they were
    • While the page is open, new positions now arrive on their own about once a minute
  • v0.6.1 — 2026-09-17

    • The page now reloads itself when you bring it back to the foreground after a while — previously a long-open tab (especially on mobile) kept showing arbitrarily old positions until you reloaded by hand
  • v0.5.4 — 2026-09-17

    • iPhone/iPad: ships were all incorrectly shown as "outdated" there and the timestamps were missing — regardless of how fresh the data actually was. Fixed; Safari could not read the AIS data's time format
  • v0.5.3 — 2026-09-17

    • Technical maintenance: internal security and stability improvements — nothing changes visibly on the site itself
  • v0.5.2 — 2026-09-17

    • Mobile view: the header and footer overflowed the screen edge on narrow phones, now wrap correctly
    • Accessibility: a skip-to-content link, a visible focus ring for keyboard use, and ships on the map are now also selectable via keyboard
  • v0.5.1 — 2026-09-14

    • Discord as a second, optional notification channel: on a confirmed destination heading to Germany, a bot now also posts to our Discord server, alongside the ntfy push
    • New "Join Discord" link in the footer for anyone interested in the community server
  • v0.4.1 — 2026-09-02

    • Logo and branding: new favicon, header logo, and a preview image for shared links (Open Graph)
    • The site is now bilingual: German (default) and English via a language switcher in the header
    • The live-status dot in the status bar now shows an actual traffic light (green/amber/red) instead of the previous colors
  • v0.3.0 — 2026-08-26

    • Track: a ship's most recently sailed route is now shown on the map
    • Heading arrow on the selected ship; plus a line to its German destination port, when one is reported
    • Map centers on a ship when you click it
    • New "Moving towards Germany" hint — estimated from actual movement, even while the reported destination is still stale
  • v0.2.1 — 2026-08-26

    • Clicking a ship now scrolls cleanly to the map, without disappearing behind the header
    • Changelog closes on outside click or Escape
    • Clearer status wording in the footer bar ("Receiving live data" instead of "Worker: Live")
  • v0.2.0 — 2026-08-26

    • Two-tier notifications: an "early" tier (first, unconfirmed Germany signal) in addition to "confirmed"
    • Push subscription as a collapsible box with a tier picker, instead of two fixed blocks
    • New footer bar with live status, version number, and changelog
  • v0.1.0 — 2026-08-25

    • First launch: live dashboard of the BYD fleet via AIS with an interactive map
    • Dark, nautical-chart-style design, click-to-select ships
    • Public JSON API for your own automations