Port Events API Upgrades Summer 2024
Marine Traffic are pleased to announce an upgrade to the Port Events products, which effects Port Events API options in Maritime 2.0 GraphQL.
API documentation: https://servicedocs-sm.kpler.com/wordpress/maritime-2-0/port-events/
- PortEventsByVessel
- PortEventsByLocation
- PortEventsByShipType
These changes are expected to be released late July or early August 2024.
Service Improvements.
The new port events will contain the following improvements:
Improved data quality from an improved algorithm.
Jumping events caused by inaccurate AIS positions resolved.
More accurate recognition of ATA and ATD.
Easier application of changes to polygons.
Quicker API response.
Greater load capacity of the events API through improved scalability.
New data fields:
- entryTime Earliest known time when vessel crossed into the polygon area associated with the event.
- vessel.staticData.timestamp Timestamp when vessel static information was received.
Constant event ID values. Previously event IDs changed when updating from open to closed status.
Improved events history. Port events history will be regenerated with all the improvements listed above.
Changing event ID values.
Clients already using Marine Traffic port events data should be aware that to achieve these improvements it is necessary to change the ID values of port event records. This will be for both historic events when querying old activity and new events going forward. This change will be immediate upon roll out of the service updates.
Port Event Entry Time
There is a new field of information in the improved port events data, this is entryTime, which records the timestamp of the AIS position that first recognises the vessel being within the polygon area used to recognise the port Event. That can be the first AIS position inside the port area, anchorage area or terminal area polygon.
The plot below is an example of a vessel AIS track for a port call, showing the point where the port entryTime is recorded and where the ATA stop position is recorded.

Release of Validated Static Data in Maritime 2.0 GraphQL Vessels
Validated Static Data (VSD) was released 2023-11-15 and is now available to all users of Maritime 2.0 GraphQL Vessels API. If you need help with this feature please contact sp@kpler.com.
Recognising that AIS messages can sometimes report incorrect or missing information for vessels, Marine Traffic uses its database of researched Vessel Characteristics (VC) information to report what we consider to be validated values for key information.
Validated values are available for a vessel’s name, imo, callsign, width, length and shipType. They are returned from the VC database when we are confident that a vessel can be identified correctly, and included in a new validated section of the staticData query response. The validated values will often be the same as those reported by the vessel in it’s AIS messages but sometimes will be different, and will be those from the VC database. Note that matching to VC data, and returning of validated values, is only applicable to vessels with IMO numbers and those reporting AIS using class A AIS.
Also, when running API calls that are filtered on a vessel’s imo, name or callsign , if the staticData.validated data is matched by the parameters of the API call, the entry will be included in the API call results (even if the non-validated data does not match).
One of the most valuable use cases of this feature is the recognition of a vessel’s correct imo number when either the wrong IMO or no IMO number is being reported by the vessel in its AIS messages. Below is an example of a Maritime 2.0 GraphQL vessels query, correcting the IMO number returned by AIS:
API request
query VslIMO {
vessels( imo:9250995 lastUpdate : {startTime:"2023-07-01T00:00:00Z" } ) {
nodes { id
staticData {
name imo mmsi aisClass callsign
flag shipType updateTimestamp
dimensions { length width a b c d }
validated {
name imo callsign shipType
dimensions { length width } }
}
lastPositionUpdate {
latitude longitude timestamp collectionType }
currentVoyage {
eta destination
matchedPort { port { name unlocode } } }
} } }Note how, in the API response below, the staticData.validated.imo value returned is the IMO number that was searched for, but the staticData.imo number, reported by the vessel in it’s AIS messages, is actually different (in this case containing an extra zero). Before the release of the VSD feature, searching for imo:9250995 would have returned no results; now, with VSD, this is recognised as the validated IMO number for the vessel and included in the API search results:
API Response
{
"data": {
"vessels": {
"nodes": [
{
"id": "4db14c7d-0728-3b4f-845c-36c02f671b73",
"staticData": {
"name": "DIMITRA C",
"imo": 92500995,
"mmsi": 256058000,
"aisClass": "A",
"callsign": "9HA3802",
"flag": "MT",
"shipType": "CONTAINER",
"updateTimestamp": "2023-07-24T04:37:24.675Z",
"dimensions": {
"length": 294,
"width": 40,
"a": 218,
"b": 76,
"c": 27,
"d": 13
},
"validated": {
"name": "DIMITRA C",
"imo": 9250995,
"callsign": "9HA3802",
"shipType": "CONTAINER",
"dimensions": {
"length": 294,
"width": 40
}
}
},
"lastPositionUpdate": {
"latitude": 25.98669,
"longitude": -76.66380833,
"timestamp": "2023-07-24T13:32:39.000Z",
"collectionType": "DYNAMIC"
},
"currentVoyage": {
"eta": "2023-07-27T23:30:00.000Z",
"destination": "MXVER",
"matchedPort": {
"port": {
"name": "Veracruz",
"unlocode": "MXVER"
}
}
}
}
]
}
}
}
The main data elements that VSD corrects are IMO number, shipType length and width dimensions.
For all except shipType a different value will be returned in the staticData.validated section of the API response.
For shipType the validated ShipType value is automatically replicated to the top level shipType,
because it is a derived value not necessarily what is transmitted in the AIS message.
So for instance if a vessel incorrectly transmits in it's AIS messages that it is a catrgo vessel but the Marine Traffic characteristics data validates the vessel as a CONTAINERSHIP, then the vessel shipType will be returned as CONTAINER in all shipType fields.
Here are counts of vessels with VSD corrections 24 hours.| VSD Category | Vessel Count |
| Vessels with IMO 0 corrected | 905 |
| Vessels with length corrected | 14802 |
| Vessels with name corrected | 6298 |
| Vessels with IMO non 0 corrected | 25 |
For more information about VSD in Maritime 2.0 GraphQL Vessels API see the documentation entry here , or please contact sp@kpler.com
Using the Historical Positions API without calling the Vessels API
Following the release of the updated Historical Positions API in October 2022, it is no longer necessary to call the Vessels API first.
The historical positions API requires a Vessel ID when requesting data for a single vessel. This ID value was previously only available from the Vessels API.
Following the API update in October 2022, the vessel ID value required to call the Historical Positions API is now available from the Maritime 2.0 GraphQL API. Users of the Historical Positions API are advised to now use Maritime 2.0 GraphQL API to obtain the vessel ID value that is then passed to the Historical Positions API.
Example of historical AIS positions for vessel COSCO BOSTON
- Find the Vessel ID value for the vessel
Call Maritime 2.0 GraphQL API using thenameorimonumber as the reference:query { vessels( imo: 9335173 lastUpdate:{ startTime:"2022-02-27T00:00:00.000Z" } ){ totalCount { relation value } nodes { id updateTimestamp staticData { name callsign timestamp updateTimestamp shipType mmsi imo callsign dimensions { width length } } } } }API result
{ "data": { "vessels": { "totalCount": { "relation": "EQUAL", "value": 1 }, "nodes": [ { "id": "41873e9b-180d-34c1-b258-8eee3b07a098", "updateTimestamp": "2023-02-27T10:42:36.926Z", "staticData": { "name": "COSCO BOSTON", "callsign": "3ELF2", "timestamp": "2023-02-27T04:41:00.027Z", "updateTimestamp": "2023-02-27T04:41:03.022Z", "shipType": "CONTAINER", "mmsi": 372934000, "imo": 9335173, "dimensions": { "width": 32, "length": 293 } } } ] } } }Note it is the top level ID in each Vessel Query result that is the id value to pass to the Historical positions API. From the query above the id value to use is:
"id": "41873e9b-180d-34c1-b258-8eee3b07a098"The id returned by the above Maritime 2.0 GraphQL vessels query is the same as that returned by the Vessels API for the same vessel.
- Use the vessel ID value in calling Historical Positions API
Using the vessel ID value now returned from Maritime 2.0 GraphQL, call the historical positions API. The vessel ID value is used to construct the URL call as below:https://rest.sml.kpler.com/vessels/41873e9b-180d-34c1-b258-8eee3b07a098/positions?timestamp_after=2023-02-27T00:00:00Z×tamp_before=2023-02-27T09:59:59ZWhile using the internal Vessel ID value, this is actually 1:1 with an instance of a vessel based on MMSI number.
If required then the Historical Positions API can be queried using a known MMSI number, without first calling the Maritime 2.0 GraphQL API. For example, to query Historical Positions API for MMSI
372934000, usemmsi_372934000instead of the vessel ID value when constructing the call to Vessels API:https://rest.sml.kpler.com/vessels/mmsi_372934000/positions?timestamp_after=2023-02-27T00:00:00Z×tamp_before=2023-02-27T09:59:59ZExample Results:
{ "paging":{ "limit":100, "self":"/vessels/mmsi_372934000/positions", "next":"FjqFcBi_JFoJAA8H0gBgAABBT5_hQsl2gxi_JVU=", "previous":"removed" }, "data":[{ "_links":{ "self":"/vessels/positions/FjqFcBi_xjUFAFsL6gE1AABBRtV4QsmuZRi-xcY=", "vessel":"/vessels/mmsi_372934000" }, "id": "FjqFcBi_xjUFAFsL6gE1AABBRtV4QsmuZRi-xcY=", "mmsi":372934000, "vessel_id":"mmsi_372934000", "timestamp":"2023-02-27T00:02:45+00:00", "created_at":"2023-02-27T00:00:54+00:00", "geometry":{ "type":"Point", "coordinates":[ 100.840614, 12.427116 ] } }] }
Vessels API End Of Life Notice for 2023-09-30
Marine Traffic announce end of life for the Vessels API from 2023-10-01.
Since early 2022, users of Vessels API have been advised to migrate to the Maritime 2.0 Vessels 2.0 GraphQL API. All product enhancements & bug fixes now only occur in the Maritime 2.0 GraphQL API. There are no reasons to continue to use the Vessels API and customers are now expected to migrate to the newer product.
All clients using the Vessels API available on https://rest.sml.kpler.com/vessels or https://rest.sml.kpler.com/vessels are requested to switch to using the Maritime 2.0 Vessels 2.0 GraphQL API by 2023-09-30.
In 23-10-01 the Vessels API will be turned off.
Maritime 2.0 GraphQL API is the future of Vessels Data API Services
Marine Traffic are continually working to improve the performance of our API services and to scale the systems to perform well with the continually growing volumes of data and clients. Maritime 2.0 GraphQL is the API platform that provides stable, scalable, performant vessels data services going forward.
The benefits of the Maritime 2.0 GraphQL API:
- Improved scalability & performance of API platform
- New more flexible and easy to use APIs using GraphQL.
- Improved and more accurate vessel identification mechanism:
- Recognizing and resolving where possible duplicate vessels reporting using the same MMSI number.
- Recognizing and resolving where possible duplicate vessels reporting using the same IMO number.
- Improved Terrestrial AIS with additional data not available in Vessels API
- Option to subscribe to real time satellite AIS.
- Extended coverage of Vessel Characteristics data, twice as many fields and vessels as reported by EVD data in Vessels API.
- Additional feature options:
- port, terminal, anchorage and canal events through graphQL query endpoints
portEventsByShipType,portEventsByShipVesselorportEventsByShipLocation - Future new features all released through graphQL.
- port, terminal, anchorage and canal events through graphQL query endpoints
Supporting customer migration
Marine Traffic are happy to offer online technical training in use of the Maritime 2.0 GraphQL API to each client migrating from the Vessels API. If you think this would be useful then please request such training by emailing sp@kpler.com .
In March 2022 we held a webinar demonstrating the differences between the Vessels API and Maritime 2.0 Vessels GraphQL API, and information necessary for customers to migrate from the REST API to Maritime 2.0 Vessels 2.0 GraphQL API.
Vessels Historical Positions API New Implementation 2022-11-17
The new version of the Historical Positions API will be released 2022-11-17 10:00 UTC.
This will look like the current implementation, but has been coded to perform better in a new computing environment.
All users of the Historical Positions API will be automatically switched to the new implementation.
What are the benefits of the new API implementation?
- Improved scalability of platform
- Improved performance
- Improved Dynamic AIS providing
- 3x volume of Dynamic AIS messages providing updates to the API
- 30% increase in vessels reported by Dynamic AIS
- Additional field coverage from Dynamic AIS
- Ability to request Historical Position History by MMSI number
- Ability to call Historical Positions API directly without calling Vessels API first.
What are the changes in the new API implementation?
vessel_id values used to make per vessel requests to the historical positions API are changing format. In the old implementation of the API they are unique ID values returned by Vessels API like this:
vessel_id: "45afbf87-a111-4cdc-8d0b-20452e282e55"In the new implementation of the API they are based on the MMSI number and look like this
vessel_id: "mmsi_636016306"It is this change of ID number that now allows the Historical Positions API to be called
- without calling Vessels API first if the MMSI is known
- by users of Maritime 2.0 graphQL QPI using a vessels MMSI number
Filter Deprecation
As part of improvements to the API system performance, the new implementation will be removing filter options from the Historical Positions API that are no longer used.
The filters to be removed are:
previous
before
Note: previous and before filters are being removed because they are not use. All users page through API results going forward using the next filter.
Comparing the output of the updated Historical Positions API and the legacy Historical Positions API
Here is to an example of the results for the same vessel from the old and new versions of the Vessels API. It should be clear that core data is the same and the format in which data is returned is the same.
Customer Support
If you have any questions about the change, please reach out to the Marine Traffic Technical support team using our Support portal or by sending an email to sp@kpler.com
Vessels API New Implementation 2022-11-17
Vessels API Upgrade & Feature Deprecation
The new implementation of Vessels API will be released 2022-11-17 10:00 UTC
This will look like the current implementation, but has been coded to perform better in a new computing environment.
qAll users of the Vessels API will be automatically switched to the new implementation.
What are the benefits of the new API implementation?
- Improved scalability of platform
- Improved performance
- Improved Dynamic AIS providing
- 3x volume of Dynamic AIS messages providing updates to the API
- 30% increase in vessels reported by Dynamic AIS
- Complete coverage of AIS positions and static data messages fields.
- Improved matching of destination to port locodes
- Improved generation of predicted_route for vessels with matched destination port locodes
As part of improvements to the API system performance, the new implementation will be removing filter options from the Vessels API that are no longer used.
The filters to be removed are:
Group 1
previous
before
Note: previous and before filters are being removed because they are unused and no longer needed. All users page through API results going forward using the next filter.
Group 2
predicted_position_within
last_known_or_predicted_position_within
The group 2 filters are being deprecated because they were based on the predicted AI feature which is no longer supported.
Group 3
general_classification(replaced byenhanced_data.vessel_and_trading_type. vessel_type)
individual_classification(replaced byenhanced_data.vessel_and_trading_type.subtype)
gross_tonnage(replaced byenhanced_data.capacity.gross_tonnage)
lifeboats
person_capacity
Group 3 fields have not been supported since 2019 and are largely replaced by the data available in the Enhanced Vessel Data (EVD) option of Vessels API. They will still be returned but with null values.
Group 4
predicted_position
predictions
The predicted_position and predictions objects will be deprecated and no longer supported. They will still be returned but with null values. For many clients this has been the case already.
Comparing the output of the updated Vessels API and the legacy Vessels API
It should be clear that core data is the same and the format in which data is returned is the same. The differences are as announced above, including a predicted route returned from the new API which had not been calculated by the old API.
Customer Support
If you have any questions about the change, please reach out to the Marine Traffic Technical support team using our Support portal or by sending an email to sp@kpler.com
Messages API performance update
Following the recent DNS update routing Messages API traffic via the new server cluster, we will release a new implementation of the Messages API.
This will look like the current implementation, but has been coded to perform better in a new computing environment.
All users of the Messages API will be automatically switched to the new implementation at this time.
What does not change?
- Tokens, URL and API parameters & format of API results will not change.
What will change?
- As part of the new API platform, on top of improved performance there will also be an improved version of Dynamic AIS™, and an additional source of Terrestrial AIS that adds coverage mainly in the Gulf of Mexico and US waterways.
- For subscribers to Dynamic AIS the volume of messages will increase 2-3 times.
- For subscribers to Marine Traffic global Terrestrial AIS the volume will increase about 10%
The response from the new implementation will match the response from the old Messages API in format, value ranges and how filters work. Internal system values may change which would be values in fields id, msg_id, since and after values. When the swap to the new implementation is made any requests made to the new implementation using pagination values from the old API will still work.
Anyone wishing to test the new system should contact Marine Traffic support to request Beta testing access. Otherwise we expect the new Messages API implementation to go live by mid-November.
Below are examples of responses from the old and new implementations of Messages API to illustrate the backward compatibility of the system.
API call used
https://rest.sml.kpler.com/messages?fields=decoded&msg_type=1&limit=1Current API result returned:
{
"paging": {
"since": "GjQKJDRmYmQ0OTI2LWVhMjYtNTI5Yy04YmQ2LTY3YmE2M2VhZjMwNRIMCKDL6ZkGEPjukOEC",
"actual": "1+",
"limit": 1
},
"data": [
{
"id": "4fbd4926-ea26-529c-8bd6-67ba63eaf305",
"nmea": "!AIVDM,1,1,,A,17WK5ggP0242RUH>QFK`
}
]
}If you have any questions concerning this update to the Messages API system then please log a support ticket requesting further guidance.
Vessels shipTypes expansion (August 2022)
Explaining the new shipType values being reported in Maritime 2.0 GraphQL Vessels
From 2022-08-30 Maritime 2.0 GraphQL for vessels will report a wider set of shipType values identified in AIS messages. When establishing Maritime 2.0 focus was given to mapping the AIS reported ship types to the real commercial ship types of cargo trading vessels, such as bulkers, tankers, gas carriers and containerships. This was done by matching AIS reported vessels to our Vessel Characteristics database. Unfortunately some of the smaller vessel types reported by AIS were all grouped together in one type category called OTHER.
As of 2022-08-30 we are updating Maritime 2.0 to report all specific vessel types identified in AIS messages.
Please note that while some vessels will still be reported with type OTHER, those with newly reported shipType values will gain a new ID in the data results. Overall the number of vessels reported as shipType OTHER will reduce significantly as vessels start to be reported with the new shipType values. Also vessels reported as PASSENGER vessels by AIS were reported as VEHICLE_PASSENGER. From this release only vessels identified in Marine Traffic Vessel Characteristics data as mixed vehicle or passenger will retain the shipType value VEHICLE_PASSENGER.
The new shipTypes values not previously reported in Maritime 2.0 are shown in the table below:
ANTI_POLLUTION- Anti Pollution Vessel
- previously reported as
OTHERup to 2022-08-30 DIVE_VESSEL- Dive Vessel
- previously reported as
OTHERup to 2022-08-30 DREDGER- Dredger
- previously reported as
OTHERup to 2022-08-30 HIGH_SPEED_CRAFT- High Speed Craft
- previously reported as
OTHERup to 2022-08-30 LAW_ENFORCEMENT- Law Enforcement
- previously reported as
OTHERup to 2022-08-30 MEDICAL_TRANS- Medical Transport
- previously reported as
OTHERup to 2022-08-30 MILITARY_OPS- Military Operations
- previously reported as
OTHERup to 2022-08-30 PASSENGER- Passenger
- previously reported as
VEHICLE_PASSENGERup to 2022-08-30 PILOT_VESSEL- Pilot Vessel
- previously reported as
OTHERup to 2022-08-30 PLEASURE_CRAFT- Pleasure Craft
- previously reported as
OTHERup to 2022-08-30 PORT_TENDER- Port Tender
- previously reported as
OTHERup to 2022-08-30 SAILING- Sailing
- previously reported as
OTHERup to 2022-08-30 SEARCH_AND_RESCUE- Search and Rescue
- previously reported as
OTHERup to 2022-08-30 SPECIAL_CRAFT- Special Craft
- previously reported as
OTHERup to 2022-08-30
Related resources
Timestamp filtering in Vessels 2.0
Explaining the lastTimestamp filter in Maritime 2.0 GraphQL Vessels
From 2022-06 Maritime 2.0 GraphQL for vessels will gain a new filter, lastTimestamp.
Unlike the filter lastPositionUpdate which filters for vessels by the time when a position update was received, the new filter lastTimestamp filters vessels on the message timestamp of any update from AIS static or position messages.
If lastTimestamp filter is not specified in a query then it will be set by default to filter out vessels with no AIS message in the last 30 days. This is intended to not return, unless specifically required, vessels that have not been updated in the previous 30 days. This is intended to reduce the volume of data being returned, unless vessels with older updates are specifically requested.
Example, comparing the use of lastTimestamp and lastPositionUpdate filter.
query {
vessels(lastPositionUpdate: {startTime: "2022-05-23T00:00:00.00Z"}) {
totalCount {
value
relation
}
}
}Returns an estimates 210,392 vessels:
{
"data": {
"vessels": {
"totalCount": {
"value": 210392,
"relation": "LOWER_OR_EQUAL"
}
}
}
}However, using the lastTimestamp filter as below, can return a slightly higher number of vessels, as it now includes vessels that have only had updates from AIS static messages too.
query {
vessels(lastTimestamp: {startTime: "2022-05-23T00:00:00.00Z"}) {
totalCount {
value
relation
}
}
}Yields to:
{
"data": {
"vessels": {
"totalCount": {
"value": 211921,
"relation": "LOWER_OR_EQUAL"
}
}
}
}The higher number of vessels returned using the lastTimestamp filter, 211921 compared to 210392, indicates that about 1500 vessels had updates from Static AIS messages but not yet from AIS position messages in the period being queried. This can be due to many reasons, including latency in AIS messages or updates to the system.
The new filter lastTimestamp allows vessels with to be queried by when AIS messages were last received. Note this is different than when the updates occurred as is used in the lastPositionTimestamp.
Example of filter differences
An AIS position message transmitted at 2022-05-23T09:59 and updated into the system at 2022-05-23T10:02 (latency of 2 minutes) would be returned by a query using filter:
lastPositionUpdate:{startTime:"2022-05-23T10:00:00.00Z"}…but not by a query using filter:
lastPositionUpdate:{startTime:"2022-05-23T09:00:00.00Z" endTime:"2022-05-23T09:59:59.59Z"}This is because the updateTimestamp would be 10:01 and outside the filtered time range. However, after being updated into the API database, the vessel with the same position message would be returned by a filter:
lastTimestamp:{startTime:"2022-05-23T09:00:00.00Z" endTime:"2022-05-23T09:59:59.59Z"}If the query is run after 10:01 when the message is recorded in the database.
Querying without timestamp filters
Now, compare querying GraphQL vessels without a timestamp. Using this query to return all vessels by shipType values that we consider the Merchant Fleet
{
vessels(
shipType: [
CAR_CARRIER, COMBINATION_CARRIER, TANKER_PRODUCT,
CONTAINER, DRY_BULK, GENERAL_CARGO,
LIVESTOCK, REEFER, ROLL_ON_ROLL_OFF,
VEHICLE_PASSENGER, GAS_CARRIER, GENERAL_TANKER,
LNG_CARRIER, TANKER_CHEMICALS, TANKER_CRUDE
]
) {
totalCount {
relation
value
}
}
}on the GraphQL Vessels system pre release of the default lastTimestamp filter we get the following result:
{
"data": {
"vessels": {
"totalCount": {
"value": 172075,
"relation": "LOWER_OR_EQUAL"
}
}
}
}On the updated GraphQL Vessels system with the default lastTimestamp filter set to 30 days we get the following result:
{
"data": {
"vessels": {
"totalCount": {
"value": 165933,
"relation": "LOWER_OR_EQUAL"
}
}
}
}Showing that about 6000 vessels have been excluded from query results because they do not have recent messages of any kind.
You can of course choose to still receive reports of vessels with updates more than 30 days old by using the lastTimestamp filter to specifically set a time from which all updated vessels are received filtered by any other parameters specified:
{
vessels(
lastTimestamp: {startTime: "2022-01-01T00:00:00.00Z"},
shipType: [
CAR_CARRIER, COMBINATION_CARRIER, TANKER_PRODUCT,
CONTAINER, DRY_BULK, GENERAL_CARGO,
LIVESTOCK, REEFER, ROLL_ON_ROLL_OFF,
VEHICLE_PASSENGER, GAS_CARRIER, GENERAL_TANKER,
LNG_CARRIER, TANKER_CHEMICALS, TANKER_CRUDE
]
) {
totalCount {
relation
value
}
}
}which returns:
{
"data": {
"vessels": {
"totalCount": {
"value": 165938,
"relation": "LOWER_OR_EQUAL"
}
}
}
}Related resources
Rate limiter updates
This blog post describes upcoming changes in rate limitation policies for the Maritime 2.0 API platform.
We recently introduced rate-limiting to prevent DDoS attacks and gracefully handle load on Maritime 2.0. The full documentation on rate limit behavior is now available.
Rate limiter for multi-root queries
As we see gradual adoption of multi-root queries among our customers, we have revised our rate-limiter policy to handle such cases appropriately. Because each root query executed in parallel and represents a complete and self-sufficient request to our underlying API, we should treat each root query as an independent request, and count it as one from the rate limiter perspective. So with new rate limiter policy, multi-root queries will be treated as several independent requests for rate limiter.
For example, currently the following query is treated as 1 request. After the update it will be counted as 2 standalone queries:
{
# first query for tankers
tankers: vessels(shipType: [TANKER_CRUDE, TANKER_PRODUCT, TANKER_CHEMICALS]) {
nodes {
staticData {
mmsi
name
}
}
}
# second query for cargo
cargo: vessels(shipType: [CONTAINER, GENERAL_CARGO]) {
nodes {
staticData {
mmsi
name
}
}
}
}The response with a new policy will look like:
{
"data": {
"tankers": { ... },
"cargo": { ... }
},
"extensions": {
"requestQuota": {
"limit": "60 req/m (burst 60)",
"remaining": 58
}
}
}As you can see, rate limiter subtracted 2 from the remaining quota, one for the cargo query and one for tankers query.
Breaking changes
There is also a subtle breaking change in the API which might be important for data integrators. To cope with wider usage of multi-root queries we should adjust the data format for some edge cases.
For example, take the multi-root query below:
{
tankers: vessels(shipType: [TANKER_CRUDE, TANKER_PRODUCT, TANKER_CHEMICALS]) {
...
}
cargo: vessels(shipType: [CONTAINER, GENERAL_CARGO]) {
...
}
}Now, let’s imagine that the tankers query completed successfully, but that the cargo query timed out for any reason; ideally a partial data response for the tankers query should still be returned. However, before this update this was not possible, and the response’s data would be null:
{
"data": null,
"errors": [{
"message": "This request timed out",
"path": ["cargo"],
"extensions": {
"code": "TIMEOUT_ERROR"
}
}],
"extensions": {
"requestQuota": {
"limit": "60 req/m (burst 60)",
"remaining": 58
}
}
}We fixed that edge case, and now a partial data response for the tankers query can be returned, along with an errors entry for the cargo query. The response would now look like this:
{
"data": {
"tankers": { ... },
"cargo": null,
},
"errors": [{
"message": "This request timed out",
"path": ["cargo"],
"extensions": {
"code": "TIMEOUT_ERROR"
}
}],
"extensions": {
"requestQuota": {
"limit": "60 req/m (burst 60)",
"remaining": 58
}
}
}These changes also affect simpler queries; for example, if an error was to be triggered during the following query:
{
vessels(shipType: [TANKER_CRUDE, TANKER_PRODUCT, TANKER_CHEMICALS]) {
nodes {
staticData {
mmsi
name
}
}
}
}The response might contain data: null or data: { vessels: null } depending on the nature of the error:
{
"data": null,
"errors": [...],
}
// or
{
"data": {
"vessels": null
},
"errors": [...],
}The second case would not have been possible earlier, and we encourage our customers to handle this case in your Marine Traffic API client.
Related resources
How does Vessels 2.0 compare to Vessels API?
Maritime 2.0 deprecates the REST Vessels API that was launched by Marine Traffic in 2018; this service has become obsolete and unable to scale with the increasing volumes of data now available in Marine Traffic data services, whereas Maritime 2.0 is built to scale and serve an expanding set of API features.
What is the difference in Request Type?
- Maritime 2.0 makes an HTTPS POST Request.
- Vessels API makes a HTTPS GET Request
The example API calls below use the curl command, a common command line utility for calling and testing APIs.
Maritime 2.0 example POST request
curl --location --request POST \
'https://api.sml.kpler.com/graphql' \
--header 'Authorization: Bearer aAAAaaA1AaAaa1A1A1AaaaA1aaaAaAAa' \
--header 'Content-Type: application/json' \
--data-raw '{"query":"query { vessels( imo:9430222) {pageInfo {hasNextPage endCursor} nodes {id updateTimestamp staticData {aisClass flag name callsign timestamp updateTimestamp shipType shipSubType mmsi imo callsign dimensions {a b c d width length } } \
lastPositionUpdate {accuracy collectionType course heading latitude longitude maneuver navigationalStatus rot speed timestamp updateTimestamp } \
currentVoyage { destination draught eta timestamp updateTimestamp matchedPort {matchScore port { name unlocode centerPoint { latitude longitude} } } } } } }","variables":{}}'
Compare this to the simpler but less flexible Vessels API request:
curl --location --request GET \
'https://rest.sml.kpler.com/vessels/?imo=9430222' \
--header 'Authorization: Bearer {Your token here}'
How do the API responses’ format compare?
The response from Maritime 2.0 is similar to that from Vessels API – the data that is returned is in a similar JSON format; but the data model for the graphQL response is slightly different. There are equivalent data items for all AIS data items that were available from the Vessels API.
Sample Maritime 2.0 API response
{
"id": "4263b0ab-9ccd-4f84-82b9-65e7d75243b8",
"updateTimestamp": "2022-02-16T00:44:48.306Z",
"staticData": {
"aisClass": "A",
"flag": "PA",
"name": "BBC RIO",
"callsign": "3E3336",
"timestamp": "2021-08-31T07:24:41.208Z",
"updateTimestamp": "2022-02-15T08:39:37.033Z",
"shipType": "GENERAL_CARGO",
"imo": 9430222,"mmsi": 352978219,
"dimensions": {
"a": 144,
"b": 17,
"c": 15,
"d": 10,
"width": 25,
"length": 161
}
},
"lastPositionUpdate": {
"accuracy": "LOW",
"collectionType": "DYNAMIC",
"course": 86.1,
"heading": 86,
"latitude": 1.267245,
"longitude": 104.22576833333332,
"maneuver": "NOT_AVAILABLE",
"navigationalStatus": "UNDER_WAY_USING_ENGINE",
"rot": 1.1160072,
"speed": 12.9,
"timestamp": "2022-02-14T20:18:27.000Z",
"updateTimestamp": "2022-02-16T00:44:48.306Z"
},
"currentVoyage": {
"destination": "SINGAPORE",
"draught": 8.2,
"eta": "2021-10-17T12:00:00.000Z",
"timestamp": "2021-10-17T09:37:17.099Z",
"updateTimestamp": "2022-02-15T08:39:37.033Z"
}
}Sample Vessels API Response
{
"id": "fd096ff2-0d1b-48d8-88f5-0fadada65139",
"name": "DIYYINAH-I",
"mmsi": 636014943,
"imo": 9487251,
"call_sign": "A8XN8",
"ship_type": "Tanker",
"class": "A",
"flag": "LR",
"length": 228,
"width": 32,
"ais_version": 0,
"created_at": "2017-08-11T19:24:21.193385+00:00",
"updated_at": "2019-09-04T16:40:09.386823+00:00",
"static_updated_at": "2019-09-02T17:26:19+00:00",
"position_updated_at": "2019-09-04T16:40:09.386823+00:00",
"last_known_position": {
"timestamp": "2019-09-04T14:59:17+00:00",
"geometry": {
"type": "Point",
"coordinates":[96.11947,5.95611]
},
"heading": 285.0,
"speed": 13.2,
"rot": 0.0,
"accuracy": null,
"collection_type": "satellite",
"draught": 8.5,
"maneuver": 0.0,
"course": 284.5
},
"most_recent_voyage": {
"eta": "2019-09-16T12:00:00+00:00",
"destination": "FUJAIRAH"
}
}How do API calls compare?
graphQL requires a more detailed “query” to be submitted when requesting data. Vessels API is a fairly fixed GET request, where the only values passed are specific filters being applied to the query. The response format is fixed and does not need specifying.
The graphQL request requires all filters to be specified, but also all required data fields for the response to be listed.
Vessels API v1. (http GET) API call for a list of vessels by IMO number
https://rest.sml.kpler.com/vessels/?limit=1&imo=9758428,9729269,9596272Maritime 2.0 graphQL (http POST) API call for a list of vessels by IMO number
query { vessels(imo:[9758428,9729269,9596272] first:1000 ) {
pageInfo { hasNextPage endCursor }
nodes { id updateTimestamp
staticData { aisClass flag name callsign timestamp updateTimestamp shipType shipSubType mmsi imo callsign dimensions { a b c d width length } }
lastPositionUpdate { accuracy collectionType course heading latitude longitude maneuver navigationalStatus rot speed timestamp updateTimestamp }
currentVoyage { destination draught eta matchedPort { matchScore port { name unlocode centerPoint { latitude longitude } } } timestamp updateTimestamp
} } } }Query what you want
graphQL allows specification of only the required data to be returned. Below is a sample graphQL query listing all available fields.
nodes {id updateTimestamp
staticData {aisClass flag name callsign timestamp updateTimestamp shipType shipSubType mmsi imo dimensions { a b c d width length } }
lastPositionUpdate { accuracy collectionType course heading
latitude longitude maneuver navigationalStatus rot speed
timestamp updateTimestamp }
currentVoyage { destination draught eta
matchedPort {matchScore port {name unlocode
centerPoint { latitude longitude } } } timestamp updateTimestamp }
} } }Here is the same graphQL query but with unrequired fields removed, showing that graphQL allows specification of only the required data items to be returned:
nodes {id updateTimestamp
staticData { name callsign updateTimestamp shipType mmsi imo
dimensions {width length } }
lastPositionUpdate { collectionType course heading
latitude longitude navigationalStatus rot speed
timestamp }
currentVoyage { destination draught eta
matchedPort {port {name unlocode } }
updateTimestamp }
}
} }How can I prepare for Maritime 2.0 (GraphQL)?
Advice for Marine Traffic clients on preparing for the next release of Marine Traffic 2.0 API using GraphQL.
Vessels API is the service that provides cleansed AIS data and, optionally, other premium features Marine Traffic offers, like routing, calculated ETAs, and Enhanced Vessel Data.
Maritime 2.0 is the second iteration of this premium solution and has been designed to take Marine Traffic forward, allowing for the easy integration of new features and for scaling performance as Marine Traffic data volumes continue to grow.
In this blog post, we hope to answer your questions about Marine Traffic 2.0 and any plans to migrate to it. However, if your questions are not answered here, then please submit a question through the client support form.
What are the benefits of Maritime 2.0 over Vessels API?
- New, more flexible, and easy-to.use APIs using graphQL
- Improved and more accurate vessel identification mechanism:
- Recognizing and resolving where possible duplicate vessels reporting using the same MMSI number.
- Recognizing and resolving where possible duplicate vessels reporting using the same IMO number.
- Maintaining a single vessel history even when changing MMSI number.
- More data available with:
- Additional AIS sources – The latest terrestrial partner added March 2021 is only available in the new services. Satellite AIS data from the next generation of Marine Traffic satellites will only be included in the new services.
- Improved and extended vessel characteristics – An additional vessel characteristics partner has been added along with additional data fields added to the new service.
- A single endpoint for all API services: Going forward a single GraphQL endpoint will be used to deliver all core Maritime API services.
- Better performance: Quicker and more stable than the V1 API.
- Faster technology development: The new platform creates a scalable architecture that allows for quicker integration of new features.
- New features exclusive to 2.0 API: Such as weather routing and port events, will be developed on this API.
When will Maritime 2.0 be available?
Marine Traffic released Maritime 2.0 (formerly known as the Vessels 2.0 API) for Beta testing on August 6, 2021. The GA release is anticipated to be mid October 2021. As with all IT development projects, this is subject to the passing of rigorous testing and no unseen technical difficulties.
How long will the Vessels API remain available?
Marine Traffic will not disable the legacy Vessels API until all clients have been migrated. We hope to achieve migration of all users by the end of 2021 and will be providing documentation, sample programs, training, and support to help make the transition as easy as possible.
Do licenses/contracts for Vessels API cover cover the GraphQL-based Maritime 2.0 API?
Marine Traffic customers have contracts granting access to different data sets and different solutions. Anyone whose contract lists Vessels API will automatically have access to Maritime 2.0.
Do we need to change the ETL code to switch to the new API?
While Marine Traffic strives to make change as minimally disruptive as possible, the data format of results from Maritime 2.0 will be different from that of the Vessels API. We expect significant similarity with only subtle differences that are still being worked out. Once the schema of Maritime 2.0 results is confirmed, details will be published and advice prepared on how to map between the 1.0 and 2.0 API results.
We anticipate ETL or DTS code will need updating to work with the new API.
Is there a change in the API structure?
The Vessels API is REST-based, whereas Maritime 2.0 is GraphQL-based. Both are HTTPS based and return results in JSON format, but the structure of the results will be different, requiring different data mappings (see the answer above about ETL). Also, the method of making data requests, known as a query in GraphQL, changes somewhat. The differences will be made clear when migration guides are released.
What will Marine Traffic do to help clients migrate from the Vessels API to Maritime 2.0?
Marine Traffic will be releasing detailed documentation about the new API and sample programs to query the API that demonstrate how to request, receive, and transform data from the new Maritime 2.0 GraphQL API. We will also be arranging webinars demonstrating how to use the new API.
Finally, as we do currently, we will offer bespoke support to all clients who use the new API. This support will be available from the Marine Traffic sales engineering team and help may be requested through the customer support form.

