Skip to Content

Asset Track

Send telemetry data for an asset to ModularIoT.

Endpoint

POST https://iot.streamhub.cl/v1/asset/track

Authentication

Requires a valid Bearer token with asset:track:write scope.

Authorization: Bearer <access_token>

Request

Headers

HeaderRequiredDescription
AuthorizationYesBearer <access_token>
Content-TypeYesapplication/json
AcceptRecommendedapplication/json for JSON responses
X-Request-IdYesUnique identifier for request tracing
X-Request-TimestampYesRequest timestamp (Unix epoch seconds)

Body (AssetTrackingData)

{ "asset_id": "A123456789", "timestamp": "2024-10-22T14:23:45Z", "type": "Truck", "owner": "Company ABC", "year": 2020, "gps": { "latitude": -33.4489, "longitude": -70.6693, "altitude": 520, "speed": 65.5, "heading": 180 }, "metrics": { "schema": "miot.metrics@1.0", "items": [ { "k": "engine.rpm", "v": 2500, "u": "rpm", "src": "obd2", "q": "ok" }, { "k": "vehicle.speed", "v": 72, "u": "km/h", "src": "obd2", "q": "ok" }, { "k": "fuel.level", "v": 65, "u": "%", "src": "obd2", "q": "ok" } ], "seq": 12345 } }

Field Reference

FieldTypeRequiredDescription
asset_idstringYesUnique identifier for the asset
timestampstringYesISO 8601 timestamp with timezone
typestringNoAsset type (e.g., “Truck”, “Container”)
ownerstringNoAsset owner name
yearintegerNoYear of manufacture
gpsobjectNoGPS location data
telecomobjectNoConnectivity information
sensorsobjectNoSensor readings
driver_infoobjectNoDriver information
co_driver_infoobjectNoCo-driver information
peripheralsobjectNoConnected peripherals
metricsobjectNoCanonical metrics (miot.metrics@1.0)
eventsarrayNoDiscrete events

GPS Object

{ "latitude": -33.4489, "longitude": -70.6693, "altitude": 520, "speed": 65.5, "heading": 180, "accuracy": 5 }
FieldTypeUnitDescription
latitudenumberdegreesWGS84 latitude (-90 to 90)
longitudenumberdegreesWGS84 longitude (-180 to 180)
altitudenumbermetersAltitude above sea level
speednumberkm/hGround speed
headingnumberdegreesDirection (0-360)
accuracynumbermetersGPS accuracy

Metrics Object (miot.metrics@1.0)

For sending canonical vehicle/IoT metrics using the standardized envelope:

{ "schema": "miot.metrics@1.0", "items": [ { "k": "engine.rpm", "v": 2150, "u": "rpm", "src": "obd2", "q": "ok" }, { "k": "engine.coolant_temp", "v": 91, "u": "C", "src": "obd2", "q": "ok" }, { "k": "battery.voltage", "v": 13.9, "u": "V", "src": "obd2", "q": "ok" }, { "k": "vehicle.speed", "v": 65, "u": "km/h", "src": "obd2", "q": "ok" } ], "seq": 12345, "device_ts": "2024-10-22T14:23:45Z" }

MetricsEnvelope Fields

FieldTypeRequiredDescription
schemastringYesMust be "miot.metrics@1.0"
itemsarrayYesArray of MetricItem objects (min 1, max 200)
seqintegerNoDevice sequence number for ordering/deduplication
device_tsstringNoDevice clock timestamp (RFC3339)
capabilitiesobjectNoOpaque metadata about supported metrics

MetricItem Fields

FieldTypeRequiredDescription
kstringYesCanonical metric key (e.g., engine.rpm)
vanyYesValue (number, boolean, string, object, or array)
ustringNoCanonical unit (e.g., rpm, km/h, C, V, %)
tsstringNoTimestamp override for this item (RFC3339)
srcstringNoSource: obd2, j1939, can, oem, derived, unknown
qstringNoQuality: ok, estimated, stale, invalid, missing
metaobjectNoOpaque metadata for traceability (PID, SPN, CAN ID)

Key pattern: Metric keys must match ^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*){1,5}$ (2-6 dot-separated lowercase segments)

→ See Reference > Metrics Registry for all available canonical metric keys.

Sensors Object

For GPS devices that send sensor data directly (without OBD-II or CAN BUS connection):

{ "odometer": 125432.5, "engine_status": 1 }
FieldTypeDescription
odometernumberTotal distance traveled in kilometers
engine_statusintegerEngine state: 1 = on, 0 = off

Use this object when the GPS device provides odometer and engine status readings directly, without relying on the vehicle’s diagnostic bus.


Response

Success (200 OK)

{ "status": "success", "message": "Message sent successfully" }

Validation Error (400 Bad Request)

{ "status": "validation_error", "message": "Request validation failed", "errors": { "assetId": "Asset ID is required and cannot be blank", "timestamp": "Timestamp is required" } }

Unauthorized (401)

Returned when the token is invalid or expired.

Internal Error (500)

{ "status": "error", "message": "Failed to publish message", "detail": "Connection timeout" }

Postman Collection

Download our ready-to-use Postman collection with all examples:
Download Postman Collection

The collection includes:

  • Authentication - Pre-configured Auth0 login flow
  • Track with GPS and Metrics - Basic OBD2 metrics example
  • Track with Batched Metrics - Multiple timestamped metrics
  • Track with Full Telemetry - Comprehensive example with all fields
  • Track with DTC Codes - Diagnostic trouble codes example

Complete Examples

Minimal Request (Required Fields Only)

# Get token first TOKEN=$(curl -s --request POST \ --url https://api.microboxlabs.com/api/v1/login \ --header 'Content-Type: application/json' \ --data '{ "client_id": "YOUR_CLIENT_ID", "client_secret": "YOUR_CLIENT_SECRET", "audience": "https://iot.streamhub.cl/v1/asset/track", "grant_type": "client_credentials" }' | jq -r '.access_token') # Send tracking data curl --request POST \ --url https://iot.streamhub.cl/v1/asset/track \ --header "Authorization: Bearer $TOKEN" \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'X-Request-Id: req-001' \ --header 'X-Request-Timestamp: 1705315800' \ --data '{ "asset_id": "A123456789", "timestamp": "2024-01-15T10:30:00Z" }'

With GPS Location

curl --request POST \ --url https://iot.streamhub.cl/v1/asset/track \ --header "Authorization: Bearer $TOKEN" \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'X-Request-Id: req-002' \ --header 'X-Request-Timestamp: 1705315800' \ --data '{ "asset_id": "A123456789", "timestamp": "2024-01-15T10:30:00Z", "type": "Truck", "gps": { "latitude": -33.4489, "longitude": -70.6693, "speed": 65.5, "heading": 180 } }'

With Canonical Metrics (OBD-II/J1939)

curl --request POST \ --url https://iot.streamhub.cl/v1/asset/track \ --header "Authorization: Bearer $TOKEN" \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'X-Request-Id: req-003' \ --header 'X-Request-Timestamp: 1705315800' \ --data '{ "asset_id": "A123456789", "timestamp": "2024-01-15T10:30:00Z", "type": "Truck", "gps": { "latitude": -33.4489, "longitude": -70.6693, "speed": 65.5 }, "metrics": { "schema": "miot.metrics@1.0", "items": [ { "k": "engine.rpm", "v": 2500, "u": "rpm", "src": "obd2", "q": "ok" }, { "k": "vehicle.speed", "v": 72, "u": "km/h", "src": "obd2", "q": "ok" }, { "k": "engine.coolant_temp", "v": 85, "u": "C", "src": "obd2", "q": "ok" }, { "k": "fuel.level", "v": 65, "u": "%", "src": "obd2", "q": "ok" }, { "k": "battery.voltage", "v": 14.2, "u": "V", "src": "obd2", "q": "ok" } ], "seq": 1001 } }'

With Batched Metrics (Multiple Timestamps)

curl --request POST \ --url https://iot.streamhub.cl/v1/asset/track \ --header "Authorization: Bearer $TOKEN" \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'X-Request-Id: req-004' \ --header 'X-Request-Timestamp: 1705315800' \ --data '{ "asset_id": "A123456789", "timestamp": "2024-01-15T10:30:30Z", "gps": { "latitude": -33.4489, "longitude": -70.6693, "speed": 58 }, "metrics": { "schema": "miot.metrics@1.0", "items": [ { "k": "engine.rpm", "v": 1800, "u": "rpm", "ts": "2024-01-15T10:30:10Z", "src": "obd2" }, { "k": "engine.rpm", "v": 1950, "u": "rpm", "ts": "2024-01-15T10:30:20Z", "src": "obd2" }, { "k": "engine.rpm", "v": 2100, "u": "rpm", "ts": "2024-01-15T10:30:30Z", "src": "obd2" }, { "k": "vehicle.speed", "v": 52, "u": "km/h", "ts": "2024-01-15T10:30:10Z", "src": "obd2" }, { "k": "vehicle.speed", "v": 55, "u": "km/h", "ts": "2024-01-15T10:30:20Z", "src": "obd2" }, { "k": "vehicle.speed", "v": 58, "u": "km/h", "ts": "2024-01-15T10:30:30Z", "src": "obd2" } ], "seq": 1002, "device_ts": "2024-01-15T10:30:30Z" } }'

With DTC Codes (Diagnostic Trouble Codes)

curl --request POST \ --url https://iot.streamhub.cl/v1/asset/track \ --header "Authorization: Bearer $TOKEN" \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'X-Request-Id: req-005' \ --header 'X-Request-Timestamp: 1705315800' \ --data '{ "asset_id": "A123456789", "timestamp": "2024-01-15T10:30:00Z", "gps": { "latitude": -33.4489, "longitude": -70.6693, "speed": 45 }, "metrics": { "schema": "miot.metrics@1.0", "items": [ { "k": "engine.rpm", "v": 2400, "u": "rpm", "src": "obd2", "q": "ok" }, { "k": "engine.coolant_temp", "v": 105, "u": "C", "src": "obd2", "q": "ok" }, { "k": "dtc.mil_on", "v": true, "src": "obd2", "q": "ok" }, { "k": "dtc.count", "v": 2, "src": "obd2", "q": "ok" }, { "k": "dtc.codes", "v": ["P0217", "P0128"], "src": "obd2", "q": "ok", "meta": { "descriptions": { "P0217": "Engine Coolant Over Temperature Condition", "P0128": "Coolant Thermostat Below Regulating Temperature" } } } ], "seq": 1003 } }'

With GPS-Connected Sensors (No OBD-II/CAN BUS)

For GPS devices that provide odometer and engine status directly:

curl --request POST \ --url https://iot.streamhub.cl/v1/asset/track \ --header "Authorization: Bearer $TOKEN" \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'X-Request-Id: req-004' \ --header 'X-Request-Timestamp: 1705315800' \ --data '{ "asset_id": "A123456789", "timestamp": "2024-01-15T10:30:00Z", "gps": { "latitude": -33.4489, "longitude": -70.6693, "speed": 65.5, "heading": 180 }, "sensors": { "odometer": 125432.5, "engine_status": 1 } }'

Python Example

import requests import time from microboxlabs_auth_manager import AuthToken # Initialize auth auth = AuthToken( client_id="YOUR_CLIENT_ID", client_secret="YOUR_CLIENT_SECRET", audience="https://iot.streamhub.cl/v1/asset/track", grant_type="client_credentials" ) # Send tracking data with metrics response = requests.post( "https://iot.streamhub.cl/v1/asset/track", headers={ "Authorization": f"Bearer {auth.get_token()}", "Content-Type": "application/json", "Accept": "application/json", "X-Request-Id": f"req-{int(time.time())}", "X-Request-Timestamp": str(int(time.time())) }, json={ "asset_id": "A123456789", "timestamp": "2024-01-15T10:30:00Z", "gps": { "latitude": -33.4489, "longitude": -70.6693, "speed": 65.5 }, "metrics": { "schema": "miot.metrics@1.0", "items": [ {"k": "engine.rpm", "v": 2500, "u": "rpm", "src": "obd2", "q": "ok"}, {"k": "vehicle.speed", "v": 72, "u": "km/h", "src": "obd2", "q": "ok"}, {"k": "engine.coolant_temp", "v": 85, "u": "C", "src": "obd2", "q": "ok"}, {"k": "fuel.level", "v": 65, "u": "%", "src": "obd2", "q": "ok"} ], "seq": 1001 } } ) print(response.json())

Common Metrics

Quick reference for frequently used canonical metrics:

KeyDescriptionUnitSource
engine.rpmEngine speedrpmOBD PID 0C
vehicle.speedVehicle speedkm/hOBD PID 0D
fuel.levelFuel tank level%OBD PID 2F
engine.coolant_tempCoolant temperatureCOBD PID 05
engine.loadCalculated engine load%OBD PID 04
battery.voltageBattery/system voltageVOBD PID 42
vehicle.odometerTotal distancekmOBD PID 31
throttle.positionThrottle opening%OBD PID 11
dtc.mil_onCheck engine light statusboolOBD PID 01
dtc.codesActive trouble codesarrayOBD Mode 03

→ See Reference > Metrics Registry for the complete catalog of canonical metrics.


Error Handling

Retry Logic

Implement exponential backoff for transient errors:

import time import requests def send_with_retry(url, headers, data, max_retries=3): for attempt in range(max_retries): try: response = requests.post(url, headers=headers, json=data) if response.status_code == 200: return response.json() elif response.status_code == 401: # Token expired - refresh and retry headers["Authorization"] = f"Bearer {get_new_token()}" elif response.status_code >= 500: # Server error - retry with backoff time.sleep(2 ** attempt) else: # Client error - don't retry return response.json() except requests.exceptions.RequestException: time.sleep(2 ** attempt) raise Exception("Max retries exceeded")

Validation Errors

When you receive a validation error, check the errors object for specific field issues:

{ "status": "validation_error", "message": "Request validation failed", "errors": { "assetId": "Asset ID is required and cannot be blank" } }

Fix the indicated fields and retry.

Last updated on