The GPS Lost endpoint plays a critical role in monitoring the stability of internet infrastructure. It will detect outages in geographic areas and determine the magnitude of the damage caused by the attack and use this data to create an overview of the affected network segments, enabling rapid response and damage mitigation.
This article will explain how to interact with the Gatehouse Maritime API to create, read, update, or delete GPS Lost detectors, with concrete code examples of how to do it.
Content overview:
The base URL for the following endpoints is:
https://mdmdemo.gatehousemaritime.com/api/ingress/ais-gps-lost-detection
To create a grounding detector, a configuration needs to be specified.
A configuration is specified in JSON format; an example of a specification can be seen below:
{
"id": 1,
"job_name": "test area gps lost",
"update_interval_hours": 24,
"historical_range": {
"lower": "2025-12-30",
"upper": "2026-01-29"
},
"geometry_shape": {
"coordinates": [
[
[
7.77392578124999,
54.39828335627755
],
[
12.74267578125001,
58.62129400565829
],
[
16.63232421875,
55.41381508026815
],
[
7.77392578124999,
54.39828335627755
]
]
],
"type": "Polygon"
},
"enabled": True,
"grid_cell_size_meters": 40000
}
The specification contains several parameters that can be tweaked to fit the use case.
To create a GPS Lost configuration, construct a POST request via the /grid-job-configs route where the payload is the specification of the configuration, as shown above.
import requests
import json
URL = (
f"https://demo.ghmaritime.com/api/ingress/ais-gps-lost-detection/grid-job-configs"
)
headers = {
"Authorization": "Basic <credentials>",
"accept": "application/json",
}
payload = {
"id": 1,
"job_name": "test area gps lost",
"update_interval_hours": 24,
"historical_range": {
"lower": "2025-12-30",
"upper": "2026-01-29"
},
"geometry_shape": {
"coordinates": [
[
[
7.77392578124999,
54.39828335627755
],
[
12.74267578125001,
58.62129400565829
],
[
16.63232421875,
55.41381508026815
],
[
7.77392578124999,
54.39828335627755
]
]
],
"type": "Polygon"
},
"enabled": True,
"grid_cell_size_meters": 40000
}
response = requests.post(URL, headers=headers, json=payload)
print(response.status_code)
response.raise_for_status()
print(json.dumps(response.json(), indent=2))
201
{
"id": 1,
"uuid": "9a427411-8918-42a3-b2b6-c7821effed73",
"created_at": "2026-02-04T07:52:35.232751Z",
"created_by": "mae",
"modified_at": "2026-02-04T07:52:35.232776Z",
"modified_by": "mae",
"owner": "de5021f4-d4d2-49b6-acbe-4cf190370439",
"acl": [],
"job_name": "test area gps lost",
"update_interval_hours": 24,
"historical_range": {
"lower": "2025-12-30",
"upper": "2026-01-29"
},
"shape_uuid": null,
"geometry_shape": {
"type": "Polygon",
"coordinates": [
[
[
7.77392578124999,
54.39828335627755
],
[
12.74267578125001,
58.62129400565829
],
[
16.63232421875,
55.41381508026815
],
[
7.77392578124999,
54.39828335627755
]
]
]
},
"enabled": true,
"grid_cell_size_meters": 40000
}
As a prerequisite, the id of the configuration needs to be known. If the id of the configuration is not known, see Get all configured GPS Lost configurations to locate the id. Additionally, the start time and end time of the time period also needs to be known and if this is not known, see Get all GPS Lost instances.
To get the results of a GPS Lost configuration, construct a GET request via the /grid-job-results/{job_id}/results endpoint and here, the id of the configuration, start time and end time should be specified in the header.
import requests
import json
URL = (
f"https://demo.ghmaritime.com/api/ingress/ais-gps-lost-detection/grid-job-results/{job_id}/results?start_time=<start_time>&end_time=<end_time>"
)
headers = {
"Authorization": "Basic <credentials>",
"accept": "application/json"
}
response = requests.get(URL, headers=headers)
print(response.status_code)
response.raise_for_status()
print(json.dumps(response.json(), indent=2))
In this example code, the job_id value is the id of the configuration and the start_time and end_time values describe the interval and is of the form “YYYY-MM-DDTHH:MM:SSZ“.
200
[
{
"job_id": 51,
"job_instance_id": 826,
"timerange": {
"lower": "2025-10-04T18:00:00Z",
"upper": "2025-10-05T00:00:00Z"
},
"status": "success",
"grid_cells_result": [
{
"element_id": 731,
"ships_w_lost_gps": 1,
"mmsi_list": [
246141000
]
},
{
"element_id": 850,
"ships_w_lost_gps": 1,
"mmsi_list": [
246141000
]
},
{
"element_id": 971,
"ships_w_lost_gps": 1,
"mmsi_list": [
246141000
]
}
]
}
]
As a prerequisite to deleting a configuration, the id of the configuration should be known, if this is not the case, see Get all configured GPS Lost configurations and find the id of the configuration.
To delete a GPS Lost configuration, construct a DELETE request via the /grid-job-configs/{job_id} where the job_id variable is the id of the configuration.
import requests
import json
URL = (
f"https://demo.ghmaritime.com/api/ingress/ais-gps-lost-detection/grid-job-configs/{job_id}"
)
headers = {
"Authorization": "Basic <credentials>",
"accept": "application/json",
}
response = requests.delete(URL, headers=headers)
print(response.status_code)
204
As a prerequisite to updating a configuration, the id of the configuration and “owner” key value pair should be known and the updated configuration should be specified.
To update a GPS Lost configuration, construct a PUT request via the /grid-job-configs/{job_id} endpoint, where the job_id variable is the id of the configuration and the request body should contain the specification of the updated configuration.
{
"id": 1,
"owner": "de5091f5-c4d3-49b6-acbe-4cf190370439",
"job_name": "test area gps lost",
"update_interval_hours": 24,
"historical_range": {
"lower": "2025-12-30",
"upper": "2026-01-29"
},
"geometry_shape": {
"coordinates": [
[
[
7.77392578124999,
54.39828335627755
],
[
12.74267578125001,
58.62129400565829
],
[
16.63232421875,
55.41381508026815
],
[
7.77392578124999,
54.39828335627755
]
]
],
"type": "Polygon"
},
"enabled": True,
"grid_cell_size_meters": 40000
}
The specification contains several parameters that can be tweaked to fit the use case.
import requests
import json
URL = (
f"https://demo.ghmaritime.com/api/ingress/ais-gps-lost-detection/grid-job-configs/{job_id}"
)
headers = {
"Authorization": "Basic <credentials>",
"accept": "application/json",
}
payload = {
"id": 1,
"owner": "ae5211g5-c4d3-49b6-acbe-4bf190370439",
"job_name": "Test1",
"update_interval_hours": 24,
"historical_range": {
"lower": "2025-12-30",
"upper": "2026-01-29"
},
"geometry_shape": {
"coordinates": [
[
[
7.77392578124999,
54.39828335627755
],
[
12.74267578125001,
58.62129400565829
],
[
16.63232421875,
55.41381508026815
],
[
7.77392578124999,
54.39828335627755
]
]
],
"type": "Polygon"
},
"enabled": True,
"grid_cell_size_meters": 40000
}
response = requests.put(URL, headers=headers, json=payload)
print(response.status_code)
response.raise_for_status()
print(json.dumps(response.json(), indent=2))
200
{
"id": 1,
"uuid": "c15db372-2387-4d08-9eb5-1902479a17c5",
"created_at": "2026-02-04T09:24:44.913174Z",
"created_by": "mae",
"modified_at": "2026-02-04T09:34:31.941128Z",
"modified_by": "mae",
"owner": "ae5211g5-c4d3-49b6-acbe-4bf190370439",
"acl": null,
"job_name": "Test2",
"update_interval_hours": 24,
"historical_range": {
"lower": "2025-12-30",
"upper": "2026-01-30"
},
"shape_uuid": null,
"geometry_shape": {
"type": "Polygon",
"coordinates": [
[
[
7.77392578124999,
54.39828335627755
],
[
12.74267578125001,
58.62129400565829
],
[
16.63232421875,
55.41381508026815
],
[
7.77392578124999,
54.39828335627755
]
]
]
},
"enabled": true,
"grid_cell_size_meters": 40000
}
To get all the current configurations of GPS Lost trackers, construct a GET request via the /grid-job-configs route.
/grid-job-configs
This will return a JSON object containing all specifications of configurations.
import requests
import json
URL = (
f"https://demo.ghmaritime.com/api/ingress/ais-gps-lost-detection/grid-job-configs"
)
headers = {
"Authorization": "Basic <credentials>",
"accept": "application/json",
"page": "<num_of_pages>",
"size": "<page_size>"
}
response = requests.get(URL, headers=headers)
print(response.status_code)
response.raise_for_status()
print(json.dumps(response.json(), indent=2))
200
{
"items": [
{
"id": 21,
"uuid": "e25d0f29-f390-42b7-b689-1e738636826e",
"created_at": "2025-05-09T06:43:51.812932Z",
"created_by": "user",
"modified_at": "2025-05-09T06:43:51.813879Z",
"modified_by": "user",
"owner": "dc4af834-235e-421a-91d1-f95b98027660",
"acl": [],
"job_name": "test area gps lost",
"update_interval_hours": 24,
"historical_range": {
"lower": "2025-05-03",
"upper": "2025-05-07"
},
"shape_uuid": "dd795e8c-3a0d-4c0d-82fe-36e4ba82811f",
"geometry_shape": null,
"enabled": true,
"grid_cell_size_meters": 40000
}
}
To get the instances of a GPS Lost configuration, construct a GET request via the /grid-job-configs/{job_id}/instances.
import requests
import json
URL = (
f"https://demo.ghmaritime.com/api/ingress/ais-gps-lost-detection/grid-job-configs/{job_id}/instances"
)
headers = {
"Authorization": "Basic <credentials>",
"accept": "application/json",
"page": "<num_of_pages>",
"size": "<page_size>"
}
response = requests.get(URL, headers=headers)
print(response.status_code)
response.raise_for_status()
print(json.dumps(response.json(), indent=2))
200
{
"items": [
{
"id": 823,
"uuid": "af2bb62e-c0fb-4bb9-ac9a-bd5e969adbfd",
"created_at": "2025-10-06T12:56:18.112724Z",
"created_by": "mae",
"modified_at": "2025-10-06T13:05:41.204768Z",
"modified_by": "grid_job_scheduler",
"job_id": 51,
"timerange": {
"lower": "2025-10-04T00:00:00Z",
"upper": "2025-10-04T06:00:00Z"
},
"status": "success",
"started_at": "2025-10-06T13:03:24.730117Z",
"finished_at": "2025-10-06T13:05:41.203526Z",
"log_message": "GPS lost grid calculated successfully"
},
...
]
}
It is then possible to use the id of the instances to get the results of the configuration.