{"openapi":"3.1.0","info":{"title":"daXos customer API","version":"1","summary":"Your fleet's measurements, read-only, as plain URLs.","description":"The same five reads as the daXos MCP connector, for software rather than agents: a TMS, a dashboard, a nightly report, an automation tool, an OpenAPI-driven assistant.\n\n**Authentication.** Every call carries `Authorization: Bearer <access key>`: the daXos access key (`dxk_…`) issued to a person on your account, or an OAuth 2.1 access token obtained the way the MCP connector obtains one. The key decides what is readable: only your account's devices, only the layers it is granted (D0, D1). Any other device answers 404.\n\n**Layers.** D0 is what the sensors measured, as received, echoes and rejected readings included, each with its flag. D1 is what survived daXos validation, with the reasons available per trip (`…/stages`). Higher layers (scores, road agent, forecasts) are not served here.\n\n**Vehicle-bus readings** (`kind=obd`) are the vehicle's own values as the dongle sends them: `can.vehicle.battery.level` = state of charge %, `can.vehicle.mileage` = odometer km, `can.hybrid.onboard.power.voltage` = HV pack V, `can.hybrid.onboard.current` = raw pack current (about −0.089 A per count, negative = discharge), cell voltages in tenths of a volt, temperatures in °C. OBD flags: 1 out of range, 2 implausible rate, 4 odometer backwards or charge rising while driving, 8 bus asleep, 16 cell max/min pair inconsistent; D1 keeps flag 0 only. A reading is stored when it changes and at least hourly when it does not.\n\n**Windows and paging.** Timestamps are unix seconds (UTC); `from`/`to` also take ISO 8601. A window is capped at 31 days and a page at 20,000 rows: follow `next_cursor` (X-Next-Cursor in CSV) until it is null.\n\n**Rate limit.** 120 calls per minute per key (HTTP 429 beyond). Read-only: there is no POST, PUT or DELETE.\n\nThe MCP connector for AI apps lives at the same host: `https://mcp.daxosdigit.com/mcp`. Keys, how to connect: https://daxosdigit.com/connect.html","contact":{"name":"daXos","email":"info@daxosdigit.com","url":"https://daxosdigit.com/connect.html"}},"servers":[{"url":"https://mcp.daxosdigit.com"}],"security":[{"accessKey":[]}],"tags":[{"name":"devices","description":"What the account may read."},{"name":"D0","description":"As measured."},{"name":"D1","description":"As validated."}],"paths":{"/v1/devices":{"get":{"tags":["devices"],"operationId":"listDevices","summary":"The devices this account may read","description":"Id, the account's own label, whether the device is connected, when it last reported, the pods it carries, and `sources`: which records it has (fixes, ble = pods, obd = vehicle bus, trips). Also how fresh the store is.","parameters":[{"name":"format","in":"query","required":false,"description":"`json` (default) or `csv`. CSV: a header row and one row per item; nested values are JSON in the cell; the page cursor is the X-Next-Cursor header. `Accept: text/csv` does the same.","schema":{"type":"string","enum":["json","csv"]}}],"responses":{"200":{"description":"The device list.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceList"}},"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"A parameter is malformed or missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid access key or token. The WWW-Authenticate header points to the OAuth metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is not granted this layer (d0 / d1).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The device is not this account's, or there is no such trip. The answer is the same for a device that does not exist: nothing about other fleets can be learned by probing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"More calls in a minute than the key allows.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/devices/{device_id}/position":{"get":{"tags":["devices"],"operationId":"getPosition","summary":"Last known position and latest readings","description":"The last position (unix ts, lat, lon, speed km/h), the latest reading of each pod parameter (`sensors`) and, for a vehicle-bus device, the latest reading of each OBD parameter (`obd`, with its plausibility flag; 0 = passed).","parameters":[{"name":"device_id","in":"path","required":true,"description":"The device id, as listed by /v1/devices.","schema":{"type":"integer"}}],"responses":{"200":{"description":"The latest state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Position"}}}},"400":{"description":"A parameter is malformed or missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid access key or token. The WWW-Authenticate header points to the OAuth metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is not granted this layer (d0 / d1).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The device is not this account's, or there is no such trip. The answer is the same for a device that does not exist: nothing about other fleets can be learned by probing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"More calls in a minute than the key allows.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/devices/{device_id}/d0":{"get":{"tags":["D0"],"operationId":"getD0","summary":"D0 — what was measured, as received","description":"`kind=fixes`: GPS fixes (ts, lat, lon, spd km/h) with raw accelerometer (ax, ay, az in g) where present. `kind=ble`: every pod packet, INCLUDING republished echoes, each with the pipeline's rejection `flag` (0 = accepted). `kind=obd`: every vehicle-bus reading (ts, param, value), INCLUDING the ones that failed the plausibility checks, each with its `flag`. `kind=accel`: the raw 0.5 s acceleration bins of one trip (needs `trip_begin`; JSON only).","parameters":[{"name":"device_id","in":"path","required":true,"description":"The device id, as listed by /v1/devices.","schema":{"type":"integer"}},{"name":"kind","in":"query","required":true,"description":"Which records.","schema":{"type":"string","enum":["fixes","ble","obd","accel"]}},{"name":"from","in":"query","required":false,"description":"Start of the window: unix seconds or ISO 8601 (a date alone is midnight UTC). Clamped to the account's start date and retention window.","schema":{"oneOf":[{"type":"number"},{"type":"string","format":"date-time"}]}},{"name":"to","in":"query","required":false,"description":"End of the window, same forms. Default: now. A window is never wider than 31 days: a wider one is cut to its last 31 days.","schema":{"oneOf":[{"type":"number"},{"type":"string","format":"date-time"}]}},{"name":"limit","in":"query","required":false,"description":"Rows per page, 1–20000.","schema":{"type":"integer","default":5000,"minimum":1,"maximum":20000}},{"name":"cursor","in":"query","required":false,"description":"The `next_cursor` of the previous page (X-Next-Cursor in CSV).","schema":{"type":"number"}},{"name":"params","in":"query","required":false,"description":"Comma-separated parameter names to keep, e.g. `temperature.2,humidity.2` or `can.vehicle.battery.level`. Filtering keeps calls small and fast.","schema":{"type":"string"}},{"name":"format","in":"query","required":false,"description":"`json` (default) or `csv`. CSV: a header row and one row per item; nested values are JSON in the cell; the page cursor is the X-Next-Cursor header. `Accept: text/csv` does the same.","schema":{"type":"string","enum":["json","csv"]}},{"name":"trip_begin","in":"query","required":false,"description":"With kind=accel: the trip's `begin` (unix seconds), from D1 trips.","schema":{"type":"integer"}}],"responses":{"200":{"description":"A page of records.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Page"}},"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"A parameter is malformed or missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid access key or token. The WWW-Authenticate header points to the OAuth metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is not granted this layer (d0 / d1).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The device is not this account's, or there is no such trip. The answer is the same for a device that does not exist: nothing about other fleets can be learned by probing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"More calls in a minute than the key allows.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/devices/{device_id}/d1":{"get":{"tags":["D1"],"operationId":"getD1","summary":"D1 — what survived daXos validation","description":"`kind=gpsv`: validated fixes with vehicle-frame longitudinal/lateral acceleration (g_long, g_lat in mg), the validated speed (spd_v) and the rejection flags. `kind=ble`: the accepted, de-echoed pod series. `kind=obd`: only the vehicle-bus readings that passed every plausibility check. `kind=trips` (`with_route=true` adds the polyline), `kind=events` (harsh brake / accel / corner, peak in mg), `kind=stops`. Windows apply to trip start / event time / stop time; gpsv, ble and obd page by cursor.","parameters":[{"name":"device_id","in":"path","required":true,"description":"The device id, as listed by /v1/devices.","schema":{"type":"integer"}},{"name":"kind","in":"query","required":true,"description":"Which records.","schema":{"type":"string","enum":["gpsv","ble","obd","trips","events","stops"]}},{"name":"from","in":"query","required":false,"description":"Start of the window: unix seconds or ISO 8601 (a date alone is midnight UTC). Clamped to the account's start date and retention window.","schema":{"oneOf":[{"type":"number"},{"type":"string","format":"date-time"}]}},{"name":"to","in":"query","required":false,"description":"End of the window, same forms. Default: now. A window is never wider than 31 days: a wider one is cut to its last 31 days.","schema":{"oneOf":[{"type":"number"},{"type":"string","format":"date-time"}]}},{"name":"limit","in":"query","required":false,"description":"Rows per page, 1–20000.","schema":{"type":"integer","default":5000,"minimum":1,"maximum":20000}},{"name":"cursor","in":"query","required":false,"description":"The `next_cursor` of the previous page (X-Next-Cursor in CSV).","schema":{"type":"number"}},{"name":"params","in":"query","required":false,"description":"Comma-separated parameter names to keep, e.g. `temperature.2,humidity.2` or `can.vehicle.battery.level`. Filtering keeps calls small and fast.","schema":{"type":"string"}},{"name":"format","in":"query","required":false,"description":"`json` (default) or `csv`. CSV: a header row and one row per item; nested values are JSON in the cell; the page cursor is the X-Next-Cursor header. `Accept: text/csv` does the same.","schema":{"type":"string","enum":["json","csv"]}},{"name":"with_route","in":"query","required":false,"description":"With kind=trips: include each trip's polyline.","schema":{"type":"boolean","default":false}}],"responses":{"200":{"description":"A page of records.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Page"}},"text/csv":{"schema":{"type":"string"}}}},"400":{"description":"A parameter is malformed or missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid access key or token. The WWW-Authenticate header points to the OAuth metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is not granted this layer (d0 / d1).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The device is not this account's, or there is no such trip. The answer is the same for a device that does not exist: nothing about other fleets can be learned by probing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"More calls in a minute than the key allows.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/devices/{device_id}/trips/{trip_begin}/stages":{"get":{"tags":["D1"],"operationId":"getTripStages","summary":"The validation chain of one trip","description":"How the accelerometer frame was validated (correlation of the mounted axes with the vehicle frame), the vibration levels, how many GPS fixes carried each rejection flag, how many were reversing, how pod readings agreed across channels, and how many vehicle-bus readings carried each plausibility flag. The audit behind the word 'validated'.","parameters":[{"name":"device_id","in":"path","required":true,"description":"The device id, as listed by /v1/devices.","schema":{"type":"integer"}},{"name":"trip_begin","in":"path","required":true,"description":"The trip's `begin` (unix seconds), as listed by D1 `kind=trips`.","schema":{"type":"integer"}}],"responses":{"200":{"description":"The validation report.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Stages"}}}},"400":{"description":"A parameter is malformed or missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"No valid access key or token. The WWW-Authenticate header points to the OAuth metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key is not granted this layer (d0 / d1).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The device is not this account's, or there is no such trip. The answer is the same for a device that does not exist: nothing about other fleets can be learned by probing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"More calls in a minute than the key allows.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"accessKey":{"type":"http","scheme":"bearer","bearerFormat":"dxk_… access key, or an OAuth 2.1 access token","description":"`Authorization: Bearer <your daXos access key>`. Keys are issued by daXos to one person each, shown once, revocable in one step; ask info@daxosdigit.com."}},"schemas":{"Error":{"type":"object","required":["error","message"],"properties":{"error":{"type":"string","enum":["bad_request","forbidden","not_acceptable","not_found","rate_limited","server_error","unauthorized"]},"message":{"type":"string"}}},"Device":{"type":"object","properties":{"id":{"type":"integer"},"label":{"type":"string","description":"Your own name for it."},"unit":{"type":["string","integer","null"]},"pods":{"type":"array","items":{"type":"string"},"description":"The pods it carries, by name; the name says which parameter index to read."},"data_from":{"type":"integer","description":"First instant served, unix seconds."},"connected":{"type":"boolean"},"last_active":{"type":["number","null"]},"last_fix_ts":{"type":["number","null"]},"sources":{"type":"array","items":{"type":"string","enum":["fixes","ble","obd","trips"]}}}},"DeviceList":{"type":"object","properties":{"tenant":{"type":"string"},"timezone":{"type":"string"},"data_from":{"type":"integer"},"layers":{"type":"array","items":{"type":"string"}},"store_last_sync":{"type":["number","null"]},"pipeline_version":{"type":["string","null"]},"items":{"type":"array","items":{"$ref":"#/components/schemas/Device"}}}},"Reading":{"type":"object","properties":{"ts":{"type":"number"},"value":{"type":"number"},"flag":{"type":"integer","description":"D0 only. 0 = passed."}}},"Position":{"type":"object","properties":{"device_id":{"type":"integer"},"label":{"type":"string"},"position":{"type":["object","null"],"properties":{"ts":{"type":"number"},"lat":{"type":"number"},"lon":{"type":"number"},"spd":{"type":"number","description":"km/h"}}},"sensors":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/Reading"},"description":"Latest reading per pod parameter, e.g. temperature.2, humidity.2, pitch.angle.2, battery.voltage.2."},"obd":{"type":"object","additionalProperties":{"$ref":"#/components/schemas/Reading"}}}},"Page":{"type":"object","properties":{"device_id":{"type":"integer"},"kind":{"type":"string"},"window":{"type":"array","items":{"type":"integer"},"minItems":2,"maxItems":2,"description":"The window actually served, after clamping."},"items":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Records of the requested kind. fixes: ts, lat, lon, spd, ax, ay, az. ble/obd: ts, param, value (+ flag in D0). gpsv: ts, lat, lon, spd_v, g_long, g_lat, flags. trips: begin, end, distance_km, duration_s… (+ route). events: ts, type, peak_mg… stops: ts, duration_s…"},"next_cursor":{"type":["number","null"],"description":"Pass as `cursor` for the next page; null = last page."}}},"Stages":{"type":"object","additionalProperties":true,"description":"device_id plus the per-stage report: accelerometer (frame validation, vibration), gps (fixes_by_flag, reversing), pods, obd (readings_by_flag)."}}}}