Skip to main content
This is a technical article describing how to use our Routing Data feature, using the map as an example.
Routing Data (Container Map GeoJSON API) is a paid feature. These APIs are subject to additional terms of usage and pricing. If you are interested in using these APIs, please contact [email protected].

Table of Contents

Overview

The GET /v2/containers/{id}/map_geojson endpoint provides all the map-related data for a container in a single GeoJSON response. The endpoint returns a GeoJSON FeatureCollection containing:
  • Port locations (Point geometries): Port of lading (POL), port of discharge (POD), and transshipment ports (TS1, TS2, etc.)
  • Current vessel location (Point geometry): The current position of the vessel if the container is currently at sea
  • Past vessel paths (LineString geometries): Historical positions of vessels for completed and in-progress legs of the journey
  • Estimated future paths (LineString geometries): Predicted vessel routes for upcoming or in-progress legs
Example of a shipment map

Getting Started

To retrieve the map data for a container, make a simple GET request to the endpoint:
Request
curl --request GET \
  --url https://api.terminal49.com/v2/containers/{id}/map_geojson \
  --header "Authorization: Token YOUR_API_TOKEN"
The response is a standard GeoJSON FeatureCollection that can be directly used with most mapping libraries (Leaflet, Mapbox GL, Google Maps, etc.).
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [
          100.896831042,
          13.065302386
        ]
      },
      "properties": {
        "feature_type": "port",
        "ports_sequence": 1,
        "ports_total": 3,
        "label": "POL",
        "name": "Laem Chabang",
        // ... more properties
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "LineString",
        "coordinates": [
          [
            100.868768333,
            13.07306
          ],
          [
            100.839155,
            13.079318333
          ],
          // ... more coordinates
          [
            118.03862,
            24.440998333
          ]
        ]
      },
      "properties": {
        "feature_type": "past_vessel_locations",
        "vessel_id": "87a12f43-766c-4078-89bc-ac6595082f7b",
        // ... more path properties
      }
    },
    // ... more features
  ]
}

Understanding the Response

GeoJSON FeatureCollection Structure

The response follows the GeoJSON specification and contains:
  • type: Always "FeatureCollection"
  • features: An array of GeoJSON Feature objects, each representing a map element (port, vessel, or route path)
Each feature contains:
  • type: Always "Feature"
  • geometry: A GeoJSON geometry object (Point or LineString)
  • properties: An object containing metadata specific to the feature type

Feature Types

The properties.feature_type field identifies what each feature represents. The following feature types are available:

Port

Geometry Type: Point Port features represent all ports in the container’s route: the port of lading (POL), port of discharge (POD), and any transshipment ports (TS1, TS2, etc.).
{
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [
      100.896831042,
      13.065302386
    ]
  },
  "properties": {
    "feature_type": "port",
    "ports_sequence": 1,
    "ports_total": 3,
    "location_id": "c5adae24-6fd4-4720-8813-976cf206feb1",
    "location_type": "Port",
    "name": "Laem Chabang",
    "state_abbr": "20",
    "state": null,
    "country_code": "TH",
    "country": "Thailand",
    "time_zone": "Asia/Bangkok",
    "inbound_eta_at": null,
    "inbound_ata_at": null,
    "outbound_etd_at": null,
    "outbound_atd_at": "2025-11-08T00:44:52Z",
    "label": "POL",
    "updated_at": "2025-12-11T09:01:08Z"
  }
}
PropertyTypeDescription
feature_typestringAlways "port"
ports_sequenceintegerThe sequence number of this port in the route (1 = POL, last = POD)
ports_totalintegerTotal number of ports in the route
location_idstringUnique identifier for the port location
location_typestringAlways "Port"
namestringName of the port
state_abbrstring | nullState abbreviation (if applicable)
statestring | nullState name (if applicable)
country_codestringISO country code
countrystringCountry name
time_zonestringIANA timezone identifier
labelstringPort label: "POL", "POD", or "TS1", "TS2", etc.
inbound_eta_atstring | nullEstimated time of arrival (ISO 8601)
inbound_ata_atstring | nullActual time of arrival (ISO 8601)
outbound_etd_atstring | nullEstimated time of departure (ISO 8601)
outbound_atd_atstring | nullActual time of departure (ISO 8601)
updated_atstring | nullLast update timestamp from the shipment (ISO 8601)

Current Vessel

Geometry Type: Point This feature is only present when the container is currently on a vessel at sea. It represents the vessel’s current position.
{
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [
      -131.128473333,
      31.023033333
    ]
  },
  "properties": {
    "feature_type": "current_vessel",
    "ports_sequence": 2,
    "vessel_id": "93fc5dce-4c7f-4089-bd28-f20cd9202ab0",
    "vessel_name": "ZIM BANGKOK",
    "vessel_imo": "9936525",
    "voyage_number": "13E",
    "vessel_location_timestamp": "2025-12-11T11:46:03Z",
    "vessel_location_heading": 108,
    "vessel_location_speed": 21,
    "departure_port_id": "ed64d446-9098-420c-ab08-c127e62509fe",
    "departure_port_name": "Xiamen",
    "departure_port_state_abbr": "FJ",
    "departure_port_state": null,
    "departure_port_country_code": "CN",
    "departure_port_country": "China",
    "departure_port_label": "TS1",
    "departure_port_atd": "2025-11-19T16:00:00Z",
    "departure_port_time_zone": "Asia/Shanghai",
    "arrival_port_id": "6129528d-846e-4571-ae16-b5328a4285ab",
    "arrival_port_name": "Savannah",
    "arrival_port_state_abbr": "GA",
    "arrival_port_state": "Georgia",
    "arrival_port_country_code": "US",
    "arrival_port_country": "United States",
    "arrival_port_label": "POD",
    "arrival_port_eta": "2025-12-31T05:00:00Z",
    "arrival_port_time_zone": "America/New_York"
  }
}
PropertyTypeDescription
feature_typestringAlways "current_vessel"
ports_sequenceintegerSequence number of the departure port for this leg
vessel_idstringUnique identifier for the vessel
vessel_namestringName of the vessel
vessel_imostringIMO number of the vessel
voyage_numberstring | nullVoyage number for this leg
vessel_location_timestampstringTimestamp of the vessel position (ISO 8601)
vessel_location_headingnumber | nullVessel heading in degrees (0-360)
vessel_location_speednumber | nullVessel speed in knots
departure_port_idstringID of the port the vessel departed from
departure_port_namestringName of the departure port
departure_port_state_abbrstring | nullState abbreviation of departure port
departure_port_statestring | nullState name of departure port
departure_port_country_codestringCountry code of departure port
departure_port_countrystringCountry name of departure port
departure_port_labelstringLabel of departure port (POL, POD, TS1, etc.)
departure_port_atdstring | nullActual time of departure from the port (ISO 8601)
departure_port_time_zonestringTimezone of departure port
arrival_port_idstring | nullID of the next port the vessel is heading to
arrival_port_namestring | nullName of the arrival port
arrival_port_state_abbrstring | nullState abbreviation of arrival port
arrival_port_statestring | nullState name of arrival port
arrival_port_country_codestring | nullCountry code of arrival port
arrival_port_countrystring | nullCountry name of arrival port
arrival_port_labelstring | nullLabel of arrival port (POL, POD, TS1, etc.)
arrival_port_etastring | nullEstimated time of arrival at the next port (ISO 8601)
arrival_port_time_zonestring | nullTimezone of arrival port

Past Vessel Locations

Geometry Type: LineString These features represent the actual historical paths taken by vessels for completed and in-progress legs of the journey. Each LineString contains a series of coordinates showing where the vessel traveled between two ports.
{
  "type": "Feature",
  "geometry": {
    "type": "LineString",
    "coordinates": [
      [
        100.868768333,
        13.07306
      ],
      [
        100.839155,
        13.079318333
      ],
      // ... many more coordinates
      [
        118.03862,
        24.440998333
      ]
    ]
  },
  "properties": {
    "feature_type": "past_vessel_locations",
    "ports_sequence": 1,
    "vessel_id": "87a12f43-766c-4078-89bc-ac6595082f7b",
    "start_time": "2025-11-08T00:44:52Z",
    "end_time": "2025-11-15T16:00:00Z",
    "point_count": 546,
    "outbound_atd_at": "2025-11-08T00:44:52Z",
    "inbound_ata_at": "2025-11-15T16:00:00Z",
    "inbound_eta_at": null
  }
}
PropertyTypeDescription
feature_typestringAlways "past_vessel_locations"
ports_sequenceintegerSequence number of the departure port for this leg
vessel_idstringUnique identifier for the vessel that traveled this path
start_timestringStart timestamp of the path (ISO 8601)
end_timestringEnd timestamp of the path (ISO 8601)
point_countintegerNumber of coordinate points in the LineString
outbound_atd_atstring | nullActual time of departure from the origin port (ISO 8601)
inbound_ata_atstring | nullActual time of arrival at the destination port (ISO 8601)
inbound_eta_atstring | nullEstimated time of arrival at the destination port (ISO 8601)

Estimated Full Leg

Geometry Type: LineString These features represent predicted vessel paths for future legs that have not yet started. The LineString shows the estimated route between two ports.
{
  "type": "Feature",
  "geometry": {
    "type": "LineString",
    "coordinates": [
      [55.059917502, 24.987353081],
      [55.234, 24.856],
      [56.123, 24.567],
      // ... intermediate estimated points
      [79.851136851, 6.942742853]
    ]
  },
  "properties": {
    "feature_type": "estimated_full_legs",
    "ports_sequence": 2,
    "previous_port_id": "94892d07-ef8f-4f76-a860-97a398c2c177",
    "next_port_id": "818ef299-aed3-49c9-b3f7-7ee205f697f6",
    "point_count": 87
  }
}
PropertyTypeDescription
feature_typestringAlways "estimated_full_legs"
ports_sequenceintegerSequence number of the departure port for this leg
previous_port_idstringID of the origin port
next_port_idstringID of the destination port
point_countintegerNumber of coordinate points in the LineString

Estimated Partial Leg

Geometry Type: LineString This feature represents the predicted path from the vessel’s current position to the next port. It is only present when the container is currently on a vessel at sea.
{
  "type": "Feature",
  "geometry": {
    "type": "LineString",
    "coordinates": [
      [
        -131.128473333,
        31.023033333
      ],
      [
        -130.9177,
        30.67224
      ],
      // ... many more coordinates
      [
        -80.91232,
        32.03728
      ]
    ]
  },
  "properties": {
    "feature_type": "estimated_partial_leg",
    "ports_sequence": 2,
    "current_port_id": "ed64d446-9098-420c-ab08-c127e62509fe",
    "next_port_id": "6129528d-846e-4571-ae16-b5328a4285ab",
    "point_count": 364
  }
}
PropertyTypeDescription
feature_typestringAlways "estimated_partial_leg"
ports_sequenceintegerSequence number of the departure port for this leg
current_port_idstringID of the port the vessel departed from
next_port_idstringID of the next port the vessel is heading to
point_countintegerNumber of coordinate points in the LineString
Note: This feature is only present when there is a current_vessel feature. The LineString starts from the vessel’s current position (which matches the current_vessel feature coordinates) and extends to the next port.

Building Your Map

To visualize a container’s journey using the GeoJSON response on your own map (similar to the embeddable map):
  1. Load the GeoJSON data into your mapping library (Leaflet, Mapbox GL, Google Maps, etc.)
  2. Filter features by type to style them differently:
    • Ports: Display as markers with labels (POL, POD, TS1, etc.)
    • Current vessel: Display as a special marker (e.g., a ship icon) with vessel information
    • Past vessel locations: Display as solid lines (representing completed journeys)
    • Estimated partial leg and Estimated full legs: Display as dashed lines (representing future predictions)
  3. Use the properties to add interactivity:
    • Show port details (name, country, timestamps) on click/hover
    • Display vessel information (name, IMO, speed, heading) for the current vessel
    • Show leg information (departure/arrival times, vessel ID) for path segments
// Fetch the GeoJSON data
fetch('https://api.terminal49.com/v2/containers/{id}/map_geojson', {
  headers: {
    'Authorization': 'Token YOUR_API_TOKEN'
  }
})
.then(response => response.json())
.then(geojson => {
  // Create a map
  const map = L.map('map').setView([20, 70], 3);
  
  // Add base layer
  L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
  
  // Process each feature
  geojson.features.forEach(feature => {
    const props = feature.properties;
    
    if (props.feature_type === 'port') {
      // Add port marker
      const marker = L.marker([feature.geometry.coordinates[1], feature.geometry.coordinates[0]])
        .addTo(map)
        .bindPopup(`<b>${props.label}</b><br>${props.name}`);
    } else if (props.feature_type === 'current_vessel') {
      // Add current vessel marker
      const vesselIcon = L.icon({
        iconUrl: 'vessel-icon.png',
        iconSize: [32, 32]
      });
      L.marker([feature.geometry.coordinates[1], feature.geometry.coordinates[0]], {icon: vesselIcon})
        .addTo(map)
        .bindPopup(`<b>${props.vessel_name}</b><br>Speed: ${props.vessel_location_speed} knots`);
    } else if (props.feature_type === 'past_vessel_locations') {
      // Add past path as solid line
      const coordinates = feature.geometry.coordinates.map(coord => [coord[1], coord[0]]);
      L.polyline(coordinates, {color: 'green', weight: 3})
        .addTo(map);
    } else if (props.feature_type === 'estimated_full_legs' || props.feature_type === 'estimated_partial_leg') {
      // Add estimated path as dashed line
      const coordinates = feature.geometry.coordinates.map(coord => [coord[1], coord[0]]);
      L.polyline(coordinates, {color: 'blue', weight: 2, dashArray: '10, 10'})
        .addTo(map);
    }
  });
});

Use Cases

Integrating Terminal49’s Vessel and Container Route APIs enables a variety of advanced capabilities:
  • Track Complete Shipment Journeys Visually: Monitor shipments across multiple legs on a map, from the port of lading to the port of discharge, including all transshipment points.
  • Identify Transshipment Details Geographically: Clearly see where transshipments occur and the routes taken between them.
  • Correlate Timestamps with Locations: Visually connect ETDs, ETAs, ATDs, and ATAs for every leg with their geographical points on the map for precise planning and exception management.
  • Improve Internal Logistics Dashboards: Offer your operations team a clear visual overview of all ongoing shipments and their current locations.

Recommendations and Best Practices

  • Polling Intervals: For active containers (currently at sea), we recommend refreshing the map data up to once per hour to get updated vessel positions. For containers that have completed their journey, you can cache the data as it won’t change.
  • Error Handling: Implement proper error handling for API requests. If a container doesn’t have route data yet, the endpoint will return an empty FeatureCollection ({"type": "FeatureCollection", "features": []}).
If you decide to create your own map:
  • Data Layering: Consider layering information on your map. Start with basic port markers and paths, then add details like vessel names, ETAs, or status on hover or click.
  • Map Library Integration: Use a robust mapping library (e.g., Leaflet, Mapbox GL, Google Maps, OpenLayers) to handle the rendering of markers, lines, and map interactivity.
  • Styling Guidelines:
    • Use distinct colors/styles for different feature types (ports, current vessel, past paths, estimated paths)
    • Consider using dashed lines for estimated paths and solid lines for completed paths
    • Add labels to port markers showing POL, POD, TS1, etc.
    • Display vessel information in popups or info panels
  • Data Interpretation:
    • The ports_sequence property helps you understand the order of ports in the journey
    • Use inbound_ata_at and outbound_atd_at to determine which legs are completed
    • The presence of a current_vessel feature indicates the container is currently at sea
  • Handling Antimeridian Crossings: When container routes cross the International Date Line (antimeridian at ±180° longitude), standard map projections can display routes incorrectly, showing lines that wrap around the entire globe. For mapping libraries that don’t natively handle antimeridian crossings, the recommended approach is to: (1) detect and split crossing LineStrings into separate segments, and (2) render map features across multiple world views (standard, East, and West) as needed. Below are more details:
    • Detection: Identify LineString features (past vessel locations or estimated paths) that cross the antimeridian by checking if consecutive coordinates have a longitude difference greater than 180°.
    • Single Crossing Solution: When one antimeridian crossing is detected:
      • Split the route into two segments: features before the crossing (based on ports_sequence) are drawn in the standard world view
      • Features after the crossing are drawn in an extended world view (East or West, depending on crossing direction)
      • Split the crossing LineString into two separate lines: one ending at the antimeridian in the standard view, and one starting from the antimeridian in the extended view
    • Multiple Crossings: For routes with more than one antimeridian crossing (rare but possible), render all features across three world views (standard, East, and West) with duplicated features. Split all crossing lines to prevent lines from wrapping across the globe.
    • No Crossings: If no antimeridian crossings are detected, render all features in the standard world view without any special handling.

Frequently Asked Questions

Q: How up-to-date is the vessel position data? A: Vessel location data is updated every 15 minutes, although that does not guarantee there will be a new position every 15 minutes due to factors like whether the vessel is transmitting or within range of a satellite or base station. Q: How accurate are the future predictions? A: Predicted future positions are based on algorithms and historical data. Their accuracy can vary based on many factors such as temporary deviations, weather conditions, seasonality, or how frequently the shipping lane is used. Q: What if a vessel deviates from the predicted path? A: Predicted paths are estimates. The historical path (once available as a past_vessel_locations feature) will show the actual route taken. Regularly refreshing data for active shipments is key to getting the most accurate information. Q: Why don’t I see a current_vessel feature for my container? A: The current_vessel feature is only present when:
  • The container is currently on a vessel at sea
  • The vessel has departed from a port (outbound_atd_at is present)
  • The next port hasn’t been reached yet (inbound_ata_at is not present)
  • A valid vessel location can be retrieved
Q: Can I get map data for multiple containers at once? A: Currently, the endpoint returns data for a single container. You’ll need to make separate API calls for each container you want to display on your map. Q: What coordinate system is used? A: All coordinates follow the GeoJSON standard: [longitude, latitude] in WGS84 (EPSG:4326) format. Q: Are the LineString coordinates simplified? A: The endpoint applies simplification to reduce the number of points in LineStrings for better performance. The simplification tolerance can vary, but the paths remain accurate for visualization purposes.