Rijkswaterstaat MIVSP op TenneT offshore platforms
Senmo Maritime Asset Intelligence
Publieke REST API/v1

Senmo MAI API

Lees platforms, devices, metingen en lifecycle events, of stuur nieuwe metingen en events in vanuit je eigen systeem. Alle ingest verschijnt binnen een seconde op de live feed en de kaart via realtime broadcast.

Base URL
https://senmo-mai.lovable.app
Content type
application/json

Quickstart

In drie stappen aangesloten. Read endpoints kun je meteen uitproberen, ingest vereist een API key.

  1. 1
    Probeer een open GET call
    Bijvoorbeeld GET /api/public/v1/platforms. Geen key nodig.
  2. 2
    Vraag een API key aan
    Neem contact op met de beheerder. Je krijgt een key met scopes op maat, bijvoorbeeld alleen ingest:measurements.
  3. 3
    Stuur je eerste batch metingen
    POST naar /api/public/ingest/measurements met header X-API-Key. Je ziet de meting direct in de UI.

Authenticatie

Read endpoints zijn open. Ingest endpoints vereisen een API key per bron, met eigen scopes.

Stuur je key mee in de header X-API-Key, of als bearer token in Authorization. Iedere key is gebonden aan een set scopes.

http
X-API-Key: smk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# of gelijkwaardig:
Authorization: Bearer smk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ingest:measurements
Metingen aanleveren.
ingest:events
Lifecycle events schrijven.
ingest:objects
Objecten upserten.

Externe UID (EUID)

Elk object en elke ingest-rij mag een eigen externe identifier meekrijgen, zodat je onze records altijd terug relateert aan jouw eigen dataset.

Twee velden
  • external_uid: de ID die jouw systeem al gebruikt, bijvoorbeeld SAP-EQ-000123 of MAX-DEV-4711.
  • external_source: optioneel label van dat systeem, bijvoorbeeld sap, maximo of gis. Laat je het leeg, dan vullen wij automatisch de naam van jouw API key in.
De combinatie (external_source, external_uid) is uniek per tabel. Twee verschillende bronnen mogen dus dezelfde UID hergebruiken zonder botsing.
Beschikbaar op
platformssublocationsdevicescomponentssensorsmeasurementslifecycle_events
Opzoeken op EUID
bash
# Vind ons device dat correspondeert met jouw Maximo-record
curl "https://senmo-mai.lovable.app/api/public/v1/devices?external_uid=MAX-DEV-4711&external_source=maximo"

# Alle platforms uit jouw SAP-koppeling
curl "https://senmo-mai.lovable.app/api/public/v1/platforms?external_source=sap"
Meesturen bij ingest
json
{
  "devices": [
    {
      "id": "dev-radar-bsa",
      "sublocation_id": "sub-bsa-01",
      "name": "Radar BSA-1",
      "type": "nautical_radar",
      "external_uid": "MAX-DEV-4711",
      "external_source": "maximo"
    }
  ]
}

Bij een tweede levering met dezelfde external_uid en external_source wordt de bestaande rij bijgewerkt in plaats van gedupliceerd.

Read endpoints

Publieke gegevens. Ideaal voor dashboards, integraties en analyses.

GET/api/public/v1/platforms
Open

Lijst van alle offshore platforms met status en coƶrdinaten.

Query parameters
NaamTypeBeschrijving
external_uidstringVind een platform op jouw eigen externe UID.
external_sourcestringBeperk tot een bepaalde bron, bijvoorbeeld sap of maximo.
curl voorbeeld
bash
curl "https://senmo-mai.lovable.app/api/public/v1/platforms?external_uid=..."
Response (200)
json
{
  "platforms": [
    {
      "id": "BSA",
      "name": "Borssele Alpha",
      "operator": "TenneT",
      "zone": "Borssele",
      "grid_type": "AC 220kV",
      "latitude": 51.7,
      "longitude": 3.06,
      "status": "operational",
      "external_uid": "SAP-EQ-000123",
      "external_source": "sap"
    }
  ]
}
GET/api/public/v1/devices
Open

Devices per platform, inclusief geneste componenten en sensoren.

Query parameters
NaamTypeBeschrijving
platform_idstringFilter op platform, bijvoorbeeld BSA.
external_uidstringVind een device op jouw eigen externe UID.
external_sourcestringBeperk tot een bepaalde bron.
curl voorbeeld
bash
curl "https://senmo-mai.lovable.app/api/public/v1/devices?platform_id=..."
Response (200)
json
{
  "devices": [
    {
      "id": "dev-radar-bsa",
      "platform_id": "BSA",
      "name": "Nautische radar BSA-1",
      "type": "nautical_radar",
      "external_uid": "MAX-DEV-4711",
      "external_source": "maximo",
      "components": [ { "id": "cmp-bsa-antenna", "name": "Antenna", "external_uid": "MAX-CMP-8802" } ],
      "sensors":    [ { "id": "sen-bsa-temp", "name": "Temperature", "unit": "celsius", "external_uid": "MAX-SEN-1201" } ]
    }
  ]
}
GET/api/public/v1/measurements
Open

Recente metingen, filterbaar per sensor en tijdvenster.

Query parameters
NaamTypeBeschrijving
sensor_idstringFilter op sensor id.
sinceISO 8601Alleen metingen vanaf dit tijdstip.
limitnumberMaximaal 1000 (default 100).
curl voorbeeld
bash
curl "https://senmo-mai.lovable.app/api/public/v1/measurements?sensor_id=..."
Response (200)
json
{
  "measurements": [
    {
      "id": "01HZ...",
      "sensor_id": "sen-17-temp",
      "ts": "2026-07-02T09:00:00Z",
      "value": 34.2,
      "quality": "good",
      "source": "ingest",
      "external_uid": "SCADA-TS-9982371",
      "external_source": "scada"
    }
  ]
}
GET/api/public/v1/events
Open

Lifecycle events per object, of geheel.

Query parameters
NaamTypeBeschrijving
object_idstringFilter op object (device, component, sensor, ...).
limitnumberMaximaal 500 (default 100).
curl voorbeeld
bash
curl "https://senmo-mai.lovable.app/api/public/v1/events?object_id=..."
Response (200)
json
{
  "events": [
    {
      "id": "01HZ...",
      "object_type": "device",
      "object_id": "dev-radar-17a",
      "event_type": "maintenance",
      "title": "Cooling fan vervangen",
      "severity": "low",
      "occurred_at": "2026-07-01T13:24:00Z",
      "maintenance_delta_days": 30,
      "replacement_delta_days": 15,
      "external_uid": "WO-2026-00815",
      "external_source": "maximo"
    }
  ]
}

Ingest endpoints

Schrijf metingen, events of objecten weg. Vereist een API key met de juiste scope.

POST/api/public/ingest/measurements
ingest:measurements

Batch van maximaal 1000 metingen aanleveren. Verschijnt direct in de live feed.

curl voorbeeld
bash
curl -X POST "https://senmo-mai.lovable.app/api/public/ingest/measurements" \
  -H "content-type: application/json" \
  -H "x-api-key: smk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  --data '{
  "measurements": [
    {
      "sensor_id": "sen-17-temp",
      "ts": "2026-07-02T09:00:00Z",
      "value": 34.2,
      "quality": "good",
      "external_uid": "SCADA-TS-9982371"
    },
    { "sensor_id": "sen-17-heartbeat", "value": 1 }
  ]
}'
Request body
json
{
  "measurements": [
    {
      "sensor_id": "sen-17-temp",
      "ts": "2026-07-02T09:00:00Z",
      "value": 34.2,
      "quality": "good",
      "external_uid": "SCADA-TS-9982371"
    },
    { "sensor_id": "sen-17-heartbeat", "value": 1 }
  ]
}
Response (200)
json
{ "inserted": 2 }
POST/api/public/ingest/events
ingest:events

Onderhoud, incident of observatie op een object. Impact op onderhoud en vervanging worden verwerkt in de ledger.

curl voorbeeld
bash
curl -X POST "https://senmo-mai.lovable.app/api/public/ingest/events" \
  -H "content-type: application/json" \
  -H "x-api-key: smk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  --data '{
  "object_type": "device",
  "object_id": "dev-radar-17a",
  "event_type": "maintenance",
  "title": "Cooling fan vervangen",
  "severity": "low",
  "maintenance_delta_days": 30,
  "replacement_delta_days": 15,
  "external_uid": "WO-2026-00815",
  "external_source": "maximo"
}'
Request body
json
{
  "object_type": "device",
  "object_id": "dev-radar-17a",
  "event_type": "maintenance",
  "title": "Cooling fan vervangen",
  "severity": "low",
  "maintenance_delta_days": 30,
  "replacement_delta_days": 15,
  "external_uid": "WO-2026-00815",
  "external_source": "maximo"
}
Response (200)
json
{ "inserted": 1 }
POST/api/public/ingest/objects
ingest:objects

Upsert van platforms, sublocaties, devices, componenten en sensoren. Referentiƫle volgorde wordt automatisch aangehouden. Elke rij mag een external_uid meekrijgen.

curl voorbeeld
bash
curl -X POST "https://senmo-mai.lovable.app/api/public/ingest/objects" \
  -H "content-type: application/json" \
  -H "x-api-key: smk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  --data '{
  "platforms":     [ { "id": "BSA", "name": "Borssele Alpha", "latitude": 51.7, "longitude": 3.06, "external_uid": "SAP-EQ-000123" } ],
  "sublocations":  [ { "id": "sub-bsa-01", "platform_id": "BSA", "name": "Sensormast", "external_uid": "SAP-LOC-000123-M1" } ],
  "devices":       [ { "id": "dev-radar-bsa", "sublocation_id": "sub-bsa-01", "name": "Radar BSA-1", "type": "nautical_radar", "external_uid": "MAX-DEV-4711" } ],
  "components":    [ { "id": "cmp-bsa-antenna", "device_id": "dev-radar-bsa", "name": "Antenna", "external_uid": "MAX-CMP-8802" } ],
  "sensors":       [ { "id": "sen-bsa-temp", "component_id": "cmp-bsa-antenna", "name": "Temperature", "unit": "celsius", "external_uid": "MAX-SEN-1201" } ]
}'
Request body
json
{
  "platforms":     [ { "id": "BSA", "name": "Borssele Alpha", "latitude": 51.7, "longitude": 3.06, "external_uid": "SAP-EQ-000123" } ],
  "sublocations":  [ { "id": "sub-bsa-01", "platform_id": "BSA", "name": "Sensormast", "external_uid": "SAP-LOC-000123-M1" } ],
  "devices":       [ { "id": "dev-radar-bsa", "sublocation_id": "sub-bsa-01", "name": "Radar BSA-1", "type": "nautical_radar", "external_uid": "MAX-DEV-4711" } ],
  "components":    [ { "id": "cmp-bsa-antenna", "device_id": "dev-radar-bsa", "name": "Antenna", "external_uid": "MAX-CMP-8802" } ],
  "sensors":       [ { "id": "sen-bsa-temp", "component_id": "cmp-bsa-antenna", "name": "Temperature", "unit": "celsius", "external_uid": "MAX-SEN-1201" } ]
}
Response (200)
json
{
  "upserted": { "platforms": 1, "sublocations": 1, "devices": 1, "components": 1, "sensors": 1 }
}

Foutafhandeling

Alle fouten komen terug als JSON met een error veld. HTTP status geeft de aard aan.

StatusBetekenisActie
200OKVerwerkt zoals verwacht.
207Multi-statusGedeeltelijk succes bij bulk upsert. Zie response body per item.
400Bad requestValidatie mislukt of ongeldige JSON. Controleer het schema.
401UnauthorizedOntbrekende of onbekende API key.
403ForbiddenKey mist de vereiste scope.
429Too many requestsRate limit geraakt. Bouw exponentiele backoff in.
500Server errorTijdelijk probleem. Probeer opnieuw en meld het aan.
Voorbeeld foutresponse
json
{
  "error": "Validation failed",
  "details": [
    { "path": ["measurements", 0, "sensor_id"], "message": "Required" }
  ]
}
Realtime updates via het mai-live broadcast kanaal: elke succesvolle ingest wordt binnen 1 seconde uitgezonden.
Test live