Skip to main content

Send your first ISO 19848 package

In this tutorial, you will use Bash and curl to send a channel definition and two simulated tank-level readings.

Customer-test environment

This tutorial uses the customer-test environment. Both the base URL and the API key must be for customer test; a production key is not interchangeable with a customer-test key.

Before you start​

You need Bash, a text editor, curl 7.76 or newer, and a customer-test ingest API key supplied by DNV for the customer + data provider connection you will use. Choose a test asset for that customer. No production data is needed.

  • Sending on your own behalf: you are both customer and data provider and typically use one API key per environment.
  • Providing data for customers: keep each customer's API key in secure storage. Select the customer-test key for the customer whose data you are sending in this exercise. Never use one customer's key for another customer's data.

The key identifies the connection, not the asset or data type. See authentication for the full boundary.

Work in an empty directory for the two JSON files you will create. The example uses IMO1234567 as a placeholder: replace it in both files with your test asset ID. Do not send these simulated readings to production or an operational asset.

1. Configure your environment​

Set the URL and the customer-test key for this customer + data provider connection:

export VISTA_GATEWAY_URL='https://vista-gateway-customer-test-api.dnv.com'
export VISTA_GATEWAY_API_KEY='<customer-test-api-key-for-this-connection>'

Keep this shell open for the remaining steps. Treat shell history containing real keys as sensitive; do not enable shell tracing (set -x) or verbose HTTP logging with credentials.

2. Create the channel definition​

Save the following as DataChannelList.json, replacing IMO1234567 with your test asset ID:

{
"Package": {
"Header": {
"ShipID": "IMO1234567",
"DataChannelListID": {
"ID": "gateway-tutorial-tank-level",
"TimeStamp": "2026-01-01T00:00:00Z"
},
"Author": "Gateway tutorial",
"DateCreated": "2026-01-01T00:00:00Z"
},
"DataChannelList": {
"DataChannel": [
{
"DataChannelID": {
"LocalID": "/dnv-v2/vis-3-4a/621.11i-S/H135/meta/qty-level/cnt-heavy.fuel.oil",
"ShortID": "TUTORIAL_TANK_LEVEL"
},
"Property": {
"DataChannelType": {
"Type": "Inst",
"UpdateCycle": 1
},
"Format": {
"Type": "Decimal"
},
"Range": {
"High": 100,
"Low": 0
},
"Unit": {
"UnitSymbol": "%",
"QuantityName": "level"
},
"Name": "Tutorial tank level"
}
}
]
}
}
}

You have defined one channel, TUTORIAL_TANK_LEVEL, with decimal values between 0 and 100. Its source identifier is mapped to a standardized Local ID. The configuration is identified by gateway-tutorial-tank-level and its timestamp.

3. Send the channel definition​

Run:

curl --fail-with-body --silent --show-error --include \
--request POST "${VISTA_GATEWAY_URL}/ISO19848/" \
--header "Authorization: ApiKey ${VISTA_GATEWAY_API_KEY}" \
--header 'Content-Type: application/json' \
--header 'User-Agent: GatewayTutorial/1.0' \
--header 'X-Package-External-Id: tutorial-channel-list-001' \
--header 'X-Package-Correlation-Id: tutorial-ingest-run-001' \
--data-binary @DataChannelList.json

Check for HTTP status 200 and a response body containing packageId:

{
"packageId": "11111111-1111-4111-8111-111111111111"
}

Your ID will be different. Save the actual ID. If the request fails, stop here and use troubleshooting before continuing: the measurements depend on this channel definition being accepted.

4. Create two readings​

Save the following as TimeSeriesData.json. Use the same test asset ID as in the first file, and leave the matching configuration reference unchanged:

{
"Package": {
"Header": {
"ShipID": "IMO1234567",
"TimeSpan": {
"Start": "2026-01-01T00:00:01Z",
"End": "2026-01-01T00:00:02Z"
},
"DateCreated": "2026-01-01T00:00:03Z",
"Author": "Gateway tutorial"
},
"TimeSeriesData": [
{
"DataConfiguration": {
"ID": "gateway-tutorial-tank-level",
"TimeStamp": "2026-01-01T00:00:00Z"
},
"TabularData": [
{
"NumberOfDataSet": 2,
"NumberOfDataChannel": 1,
"DataChannelID": ["TUTORIAL_TANK_LEVEL"],
"DataSet": [
{
"TimeStamp": "2026-01-01T00:00:01Z",
"Value": ["50.0"]
},
{
"TimeStamp": "2026-01-01T00:00:02Z",
"Value": ["49.5"]
}
]
}
]
}
]
}
}

The two rows contain simulated readings of 50.0% and 49.5%, one second apart. Each row has one value for the one channel listed in DataChannelID. Notice that ISO 19848 represents these values as strings in the JSON document.

5. Send the readings​

Run:

curl --fail-with-body --silent --show-error --include \
--request POST "${VISTA_GATEWAY_URL}/ISO19848/" \
--header "Authorization: ApiKey ${VISTA_GATEWAY_API_KEY}" \
--header 'Content-Type: application/json' \
--header 'User-Agent: GatewayTutorial/1.0' \
--header 'X-Package-External-Id: tutorial-measurements-001' \
--header 'X-Package-Correlation-Id: tutorial-ingest-run-001' \
--data-binary @TimeSeriesData.json

Check for HTTP status 200 and a new packageId. Save this ID separately from the channel-list package ID. You have now submitted the two measurement rows in one package.

Acceptance does not confirm downstream processing. Repeating the tutorial can create additional packages. To apply the workflow to your own data, follow Set up ISO 19848 ingest.