Asset Track
Send telemetry data for an asset to ModularIoT.
Endpoint
POST https://iot.streamhub.cl/v1/asset/trackAuthentication
Requires a valid Bearer token with asset:track:write scope.
Authorization: Bearer <access_token>Request
Headers
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer <access_token> |
Content-Type | Yes | application/json |
Accept | Recommended | application/json for JSON responses |
X-Request-Id | Yes | Unique identifier for request tracing |
X-Request-Timestamp | Yes | Request 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
| Field | Type | Required | Description |
|---|---|---|---|
asset_id | string | Yes | Unique identifier for the asset |
timestamp | string | Yes | ISO 8601 timestamp with timezone |
type | string | No | Asset type (e.g., “Truck”, “Container”) |
owner | string | No | Asset owner name |
year | integer | No | Year of manufacture |
gps | object | No | GPS location data |
telecom | object | No | Connectivity information |
sensors | object | No | Sensor readings |
driver_info | object | No | Driver information |
co_driver_info | object | No | Co-driver information |
peripherals | object | No | Connected peripherals |
metrics | object | No | Canonical metrics (miot.metrics@1.0) |
events | array | No | Discrete events |
GPS Object
{
"latitude": -33.4489,
"longitude": -70.6693,
"altitude": 520,
"speed": 65.5,
"heading": 180,
"accuracy": 5
}| Field | Type | Unit | Description |
|---|---|---|---|
latitude | number | degrees | WGS84 latitude (-90 to 90) |
longitude | number | degrees | WGS84 longitude (-180 to 180) |
altitude | number | meters | Altitude above sea level |
speed | number | km/h | Ground speed |
heading | number | degrees | Direction (0-360) |
accuracy | number | meters | GPS 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
| Field | Type | Required | Description |
|---|---|---|---|
schema | string | Yes | Must be "miot.metrics@1.0" |
items | array | Yes | Array of MetricItem objects (min 1, max 200) |
seq | integer | No | Device sequence number for ordering/deduplication |
device_ts | string | No | Device clock timestamp (RFC3339) |
capabilities | object | No | Opaque metadata about supported metrics |
MetricItem Fields
| Field | Type | Required | Description |
|---|---|---|---|
k | string | Yes | Canonical metric key (e.g., engine.rpm) |
v | any | Yes | Value (number, boolean, string, object, or array) |
u | string | No | Canonical unit (e.g., rpm, km/h, C, V, %) |
ts | string | No | Timestamp override for this item (RFC3339) |
src | string | No | Source: obd2, j1939, can, oem, derived, unknown |
q | string | No | Quality: ok, estimated, stale, invalid, missing |
meta | object | No | Opaque 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):
{
"acceleration": {
"x_axis": 1.5,
"y_axis": -0.5,
"z_axis": 2.0,
"g_force": 1.2
},
"gyroscope": {
"rotation_rate_x": 5.5,
"rotation_rate_y": -3.2,
"rotation_rate_z": 1.8
},
"odometer": 125432.5,
"engine_status": 1
}| Field | Type | Description |
|---|---|---|
acceleration | object | Linear acceleration from the device’s accelerometer (see below) |
gyroscope | object | Angular rotation rates from the device’s gyroscope (see below) |
odometer | number | Total distance traveled in kilometers |
engine_status | integer | Engine state: 1 = on, 0 = off |
Use this object when the GPS device provides inertial, odometer or engine status readings directly, without relying on the vehicle’s diagnostic bus. All sub-fields are optional — send only what the device reports.
Acceleration
Linear acceleration on each axis of the device’s accelerometer, plus the total magnitude. Used to detect harsh braking, hard acceleration, sharp cornering, impacts and crash events.
| Field | Type | Unit | Range | Description |
|---|---|---|---|---|
x_axis | number | g | -3.0 to 3.0 | Acceleration along the X axis (typically lateral) |
y_axis | number | g | -3.0 to 3.0 | Acceleration along the Y axis (typically longitudinal) |
z_axis | number | g | -3.0 to 3.0 | Acceleration along the Z axis (typically vertical) |
g_force | number | g | 0.0 to 5.0 | Total acceleration magnitude, including gravity |
Values are reported in units of g (standard gravity, 1 g ≈ 9.80665 m/s²). Axis orientation depends on how the device is mounted — refer to the device datasheet for the sensor frame.
Gyroscope
Angular rotation rate around each axis of the device’s gyroscope. Used to detect rollover, aggressive maneuvers and orientation changes.
| Field | Type | Unit | Range | Description |
|---|---|---|---|---|
rotation_rate_x | number | rad/s | -10.0 to 10.0 | Rotation rate around the X axis (roll) |
rotation_rate_y | number | rad/s | -10.0 to 10.0 | Rotation rate around the Y axis (pitch) |
rotation_rate_z | number | rad/s | -10.0 to 10.0 | Rotation rate around the Z axis (yaw) |
Values are reported in radians per second. Multiply by
180/π(≈ 57.2958) to convert to degrees per second if your downstream pipeline expects °/s.
Events Object
For GPS devices or providers that pre-compute discrete asset events (harsh braking, hard acceleration, sharp cornering, speeding, impacts). Use this object when the provider already delivers the typed event — with severity and threshold — rather than only the raw sensor reading.
{
"events": [
{
"event_type": "hard_brake",
"timestamp": "2026-04-23T14:32:10Z",
"severity": "high",
"threshold_exceeded": true,
"additional_info": {
"g_force": 0.82,
"speed_at_event": 74.5,
"cargo_weight": 5000
}
}
]
}| Field | Type | Required | Description |
|---|---|---|---|
event_type | string | Yes | Event type. See catalog below. |
timestamp | string | Yes | ISO 8601 timestamp of the event (may differ from the envelope timestamp). |
severity | string | No | Severity reported by the provider: low, medium, high. |
threshold_exceeded | boolean | No | true if the event exceeded the provider’s configured threshold. |
additional_info | object | No | Event metadata (see below). |
event_type catalog
| Value | Description |
|---|---|
hard_brake | Harsh braking detected by the provider from longitudinal acceleration. |
hard_accel | Hard acceleration detected by the provider from longitudinal acceleration. |
hard_turn | Sharp cornering / aggressive lateral maneuver detected by the provider from the gyroscope or lateral acceleration. |
speeding | Over-speed relative to the configured limit. |
impact | Impact / collision detected by the provider from a g-force spike. |
The
event_typefield is a free-form string: the values above are the convention supported by the symptoms pipeline. Other values are accepted and persisted, but will not trigger downstream rules.
additional_info
| Field | Type | Unit | Range | Description |
|---|---|---|---|---|
g_force | number | g | 0.0 to 5.0 | G-force measured during the event. |
speed_at_event | number | km/h | 0.0 to 250.0 | Asset speed at the moment of the event. |
cargo_weight | number | kg | 0.0 to 20000.0 | Cargo weight at the moment of the event, if the device reports it. |
Prefer
events[]for data already typed by the provider (hard brake, hard acceleration, hard turn). If you only have the raw accelerometer or gyroscope reading, send it insensors.acceleration/sensors.gyroscopeand let the pipeline derive the event.
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
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
- Track with Provider Events - Typed events (hard_brake, hard_accel, hard_turn)
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
}
}'With Accelerometer and Gyroscope (IMU Sensors)
For GPS devices equipped with an inertial measurement unit that reports acceleration and rotation:
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-006' \
--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": {
"acceleration": {
"x_axis": 1.5,
"y_axis": -0.5,
"z_axis": 2.0,
"g_force": 1.2
},
"gyroscope": {
"rotation_rate_x": 5.5,
"rotation_rate_y": -3.2,
"rotation_rate_z": 1.8
},
"odometer": 125432.5,
"engine_status": 1
}
}'With Provider Events (Hard Brake/Accel/Turn)
For GPS devices or providers that pre-compute discrete driving events and send them typed — with severity and threshold — inside the events[] array.
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-007' \
--header 'X-Request-Timestamp: 1740492537' \
--data '{
"asset_id": "TTBJ72",
"timestamp": "2026-02-13T13:48:57Z",
"gps": {
"latitude": -29.810218,
"longitude": -71.282617,
"speed": 74.5,
"heading": 315
},
"events": [
{
"event_type": "hard_brake",
"timestamp": "2026-02-13T13:48:55Z",
"severity": "high",
"threshold_exceeded": true,
"additional_info": { "g_force": 0.82, "speed_at_event": 74.5, "cargo_weight": 5000 }
},
{
"event_type": "hard_accel",
"timestamp": "2026-02-13T13:48:40Z",
"severity": "medium",
"threshold_exceeded": true,
"additional_info": { "g_force": 0.61, "speed_at_event": 42.0 }
},
{
"event_type": "hard_turn",
"timestamp": "2026-02-13T13:48:30Z",
"severity": "medium",
"threshold_exceeded": true,
"additional_info": { "g_force": 0.55, "speed_at_event": 58.0 }
}
]
}'Node.js (fetch)
const res = await fetch("https://iot.streamhub.cl/v1/asset/track", {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
Accept: "application/json",
"X-Request-Id": crypto.randomUUID(),
"X-Request-Timestamp": String(Math.floor(Date.now() / 1000)),
},
body: JSON.stringify({
asset_id: "TTBJ72",
timestamp: "2026-02-13T13:48:57Z",
gps: { latitude: -29.810218, longitude: -71.282617, speed: 74.5, heading: 315 },
events: [
{
event_type: "hard_brake",
timestamp: "2026-02-13T13:48:55Z",
severity: "high",
threshold_exceeded: true,
additional_info: { g_force: 0.82, speed_at_event: 74.5, cargo_weight: 5000 },
},
{
event_type: "hard_accel",
timestamp: "2026-02-13T13:48:40Z",
severity: "medium",
threshold_exceeded: true,
additional_info: { g_force: 0.61, speed_at_event: 42.0 },
},
{
event_type: "hard_turn",
timestamp: "2026-02-13T13:48:30Z",
severity: "medium",
threshold_exceeded: true,
additional_info: { g_force: 0.55, speed_at_event: 58.0 },
},
],
}),
});
if (!res.ok) throw new Error(`asset/track ${res.status}: ${await res.text()}`);Python (requests)
import time, uuid, requests
res = requests.post(
"https://iot.streamhub.cl/v1/asset/track",
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
"Accept": "application/json",
"X-Request-Id": str(uuid.uuid4()),
"X-Request-Timestamp": str(int(time.time())),
},
json={
"asset_id": "TTBJ72",
"timestamp": "2026-02-13T13:48:57Z",
"gps": {"latitude": -29.810218, "longitude": -71.282617, "speed": 74.5, "heading": 315},
"events": [
{
"event_type": "hard_brake",
"timestamp": "2026-02-13T13:48:55Z",
"severity": "high",
"threshold_exceeded": True,
"additional_info": {"g_force": 0.82, "speed_at_event": 74.5, "cargo_weight": 5000},
},
{
"event_type": "hard_accel",
"timestamp": "2026-02-13T13:48:40Z",
"severity": "medium",
"threshold_exceeded": True,
"additional_info": {"g_force": 0.61, "speed_at_event": 42.0},
},
{
"event_type": "hard_turn",
"timestamp": "2026-02-13T13:48:30Z",
"severity": "medium",
"threshold_exceeded": True,
"additional_info": {"g_force": 0.55, "speed_at_event": 58.0},
},
],
},
timeout=10,
)
res.raise_for_status()Java (HttpClient)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Instant;
import java.util.UUID;
String body = """
{
"asset_id": "TTBJ72",
"timestamp": "2026-02-13T13:48:57Z",
"gps": { "latitude": -29.810218, "longitude": -71.282617, "speed": 74.5, "heading": 315 },
"events": [
{ "event_type": "hard_brake", "timestamp": "2026-02-13T13:48:55Z", "severity": "high",
"threshold_exceeded": true,
"additional_info": { "g_force": 0.82, "speed_at_event": 74.5, "cargo_weight": 5000 } },
{ "event_type": "hard_accel", "timestamp": "2026-02-13T13:48:40Z", "severity": "medium",
"threshold_exceeded": true,
"additional_info": { "g_force": 0.61, "speed_at_event": 42.0 } },
{ "event_type": "hard_turn", "timestamp": "2026-02-13T13:48:30Z", "severity": "medium",
"threshold_exceeded": true,
"additional_info": { "g_force": 0.55, "speed_at_event": 58.0 } }
]
}
""";
HttpRequest req = HttpRequest.newBuilder(URI.create("https://iot.streamhub.cl/v1/asset/track"))
.header("Authorization", "Bearer " + token)
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.header("X-Request-Id", UUID.randomUUID().toString())
.header("X-Request-Timestamp", String.valueOf(Instant.now().getEpochSecond()))
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> res = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());
if (res.statusCode() >= 300) throw new RuntimeException("asset/track " + res.statusCode() + ": " + res.body());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:
| Key | Description | Unit | Source |
|---|---|---|---|
engine.rpm | Engine speed | rpm | OBD PID 0C |
vehicle.speed | Vehicle speed | km/h | OBD PID 0D |
fuel.level | Fuel tank level | % | OBD PID 2F |
engine.coolant_temp | Coolant temperature | C | OBD PID 05 |
engine.load | Calculated engine load | % | OBD PID 04 |
battery.voltage | Battery/system voltage | V | OBD PID 42 |
vehicle.odometer | Total distance | km | OBD PID 31 |
throttle.position | Throttle opening | % | OBD PID 11 |
dtc.mil_on | Check engine light status | bool | OBD PID 01 |
dtc.codes | Active trouble codes | array | OBD 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.