openJII MQTT API (AWS IoT Core)
v1.0.0MQTT
API Information: This AsyncAPI specification defines the MQTT topics and message schemas for AWS IoT Core. It details channels for device status updates and sensor data, allowing devices to publish their state and sensor readings securely.
Servers
production
| URL | a123456789.iot.us-east-1.amazonaws.com |
| Protocol | MQTT |
| Description | AWS IoT Core production endpoint |
Security
sigv4
Type: apiKey
Location: user
AWS Signature Version 4 is used to sign the MQTT connection requests to AWS IoT Core.
Operations
SUBSCRIBE
experiment/data_ingest/v1/{experimentId}/{sensorType}/{sensorVersion}/{sensorId}Channel for ingesting experiment sensor data. This shape carries no
protocol attribution in the topic; publishers carry it in the payload
instead (`protocol_id`, see the message schema), alongside the workbook
attribution fields.
The path parameters represent:
- experimentId: Unique identifier of the experiment (e.g., exp123).
- sensorType: The type or family of sensor (e.g., MutlispeQ, Ambit...).
- sensorVersion: Sensor firmware/hardware revision (without the 'v' prefix, e.g., 1, 2.1).
- sensorId: Unique sensor identifier (UUID format recommended).
Parameters
| Name | Type | Description |
|---|---|---|
experimentId | string | Unique identifier of the experiment (e.g., exp123). |
sensorType | string | The type or family of sensor (e.g., MutlispeQ, Ambit...). |
sensorVersion | string | Sensor firmware/hardware revision (without the 'v' prefix, e.g., 1, 2.1). |
sensorId | string | Unique sensor identifier (UUID format recommended). |
Subscribe Operation
Operation ID: ingestExperimentData
Summary: Ingest experiment sensor data.
SUBSCRIBE
experiment/data_ingest/v1/{experimentId}/{sensorType}/{sensorVersion}/{sensorId}/{protocolId}TRANSITIONAL: the legacy ingest shape with a trailing protocolId segment,
published by fielded mobile builds. New publishers must use the shape
without protocolId.
Parameters
| Name | Type | Description |
|---|---|---|
experimentId | string | Unique identifier of the experiment (e.g., exp123). |
sensorType | string | The type or family of sensor (e.g., MutlispeQ, Ambit...). |
sensorVersion | string | Sensor firmware/hardware revision (without the 'v' prefix, e.g., 1, 2.1). |
sensorId | string | Unique sensor identifier (UUID format recommended). |
protocolId | string | Legacy protocol identifier carried in the trailing topic segment; the lean topic shape omits it. |
Subscribe Operation
Operation ID: ingestExperimentDataLegacy
Summary: Ingest experiment sensor data (legacy topic shape).
PUBLISH
device/scripts/v1/{sensorType}/{sensorVersion}/{thingName}Channel for delivering behaviour scripts to a device. The cloud publishes and
the device subscribes, then applies the script to its attached sensor. Messages
are published retained at QoS 1 so a device that reconnects immediately receives
the current script for its topic.
The path parameters represent:
- sensorType: The target sensor family (e.g., MultispeQ, Ambit...).
- sensorVersion: Target firmware/hardware revision (without the 'v' prefix, e.g., 1, 2.1).
- thingName: AWS IoT Thing name of the target device. The IoT policy binds this segment to ${iot:Connection.Thing.ThingName}, so a device (authenticated by its X.509 certificate) can only subscribe to and receive its own scripts.
Parameters
| Name | Type | Description |
|---|---|---|
sensorType | string | The target sensor family (e.g., MultispeQ, Ambit...). |
sensorVersion | string | Target firmware/hardware revision (without the 'v' prefix, e.g., 1, 2.1). |
thingName | string | AWS IoT Thing name of the target device (e.g., dom_ludo_prototype_ambyte_thing_v2). |
Publish Operation
Operation ID: deliverDeviceScript
Summary: Deliver a behaviour script to a device.
Messages
Experiment Data Ingestion Message
A message containing sensor data for an experiment.
| Name | ExperimentDataMessage |
| Content Type | application/json |
Payload Schema
{
"type": "object",
"additionalProperties": true,
"properties": {
"sample": {
"type": "string",
"description": "Sensor sample data: a JSON object of readings or an array of them (a burst). Raw JSON string, or gzip+base64 encoded when _sample_encoding is set.\n"
},
"_sample_encoding": {
"type": "string",
"enum": [
"gzip+base64"
],
"description": "When present, the `sample` field is compressed (gzip) and base64-encoded. Absent on raw (uncompressed) payloads.\n"
},
"timestamp": {
"type": "string",
"description": "ISO 8601 timestamp with UTC offset captured at measurement time using the synced clock (e.g. \"2026-03-09T10:30:00.000-05:00\").\n"
},
"timezone": {
"type": "string",
"description": "IANA timezone identifier at measurement time (e.g. \"America/Chicago\"). Preserved across retries so the original measurement-time timezone is never lost.\n"
},
"protocol_id": {
"type": "string",
"description": "Platform id of the protocol that produced this measurement, resolved by the publisher per result (a workbook run can span several protocols). Required on the lean topic shape for the row to be attributed; the sentinel value \"questions\" marks question-only uploads. On the legacy topic shape the topic's trailing segment takes precedence.\n"
},
"workbook_version_id": {
"type": "string",
"description": "Platform id of the workbook version this measurement was produced under. Absent outside workbook runs.\n"
},
"workbook_id": {
"type": "string",
"description": "Platform id of the workbook the producing version belongs to. Mobile-local replay aid (re-running the stored macro resolves the producing workbook even if the experiment is re-linked); the pipeline keys on workbook_version_id.\n"
},
"workbook_run_id": {
"type": "string",
"description": "Publisher-minted id shared by every measurement of one workbook run, correlating results across devices and protocols.\n"
},
"macro_context": {
"type": "string",
"description": "JSON-encoded macro execution context; stays a string because its keys are dynamic.\n"
},
"macros": {
"type": "array",
"description": "Macros applied to this measurement. Publishers that embed a macros array (of macro ids) inside each sample object instead may omit this field; the pipeline reads either.\n",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Platform macro id."
},
"name": {
"type": "string"
},
"filename": {
"type": "string"
}
}
}
},
"questions": {
"type": "array",
"description": "Question/answer entries attached to the measurement.",
"items": {
"type": "object",
"properties": {
"question_label": {
"type": "string"
},
"question_text": {
"type": "string"
},
"question_answer": {
"type": "string"
}
}
}
},
"annotations": {
"type": "array",
"description": "Annotations attached at capture time.",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"rowId": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"comment",
"flag"
]
},
"content": {
"type": "object",
"properties": {
"text": {
"type": "string"
},
"flagType": {
"type": "string"
}
}
},
"createdBy": {
"type": "string"
},
"createdByName": {
"type": "string"
},
"createdAt": {
"type": "string"
},
"updatedAt": {
"type": "string"
}
}
}
},
"user_id": {
"type": "string",
"description": "Platform id of the contributing user's session."
},
"device_id": {
"type": "string",
"description": "Device identifier as reported by the instrument."
},
"device_name": {
"type": "string",
"description": "Device name as reported by the instrument."
},
"device_version": {
"type": "string",
"description": "Firmware version as reported by the device."
},
"device_firmware": {
"type": "string",
"description": "Firmware identifier as reported by the device."
},
"device_battery": {
"type": "number",
"description": "Battery reading as the device reports it; the unit is device-defined (volts on some families, percent on others).\n"
},
"output": {
"type": "string",
"description": "Device-native output block, passed through as text."
},
"latitude": {
"type": "number",
"description": "GPS latitude at measurement time, if available."
},
"longitude": {
"type": "number",
"description": "GPS longitude at measurement time, if available."
}
},
"required": [
"timestamp"
]
}Example
Example 1
{
"timestamp": "2026-03-09T10:30:00.000-05:00",
"timezone": "America/Chicago",
"protocol_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"sample": "{\"moisture\": 30.5, \"temperature\": 22.1}",
"device_version": "1.1.0",
"device_battery": 4.1
}Device Script Update Message
A protocol measurement script delivered from the cloud to a device.
| Name | DeviceScriptMessage |
| Content Type | application/json |
Payload Schema
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"script_update"
],
"description": "Command discriminator, so the same topic can carry future command types."
},
"id": {
"type": "string",
"description": "Unique update identifier (e.g. upd-2026-06-08-001). Lets a device skip an update it has already applied."
},
"payload": {
"type": "string",
"description": "The protocol measurement script body (Lua source), sent inline. May be a raw string or a gzip+base64 encoded string when _payload_encoding is set.\n"
},
"_payload_encoding": {
"type": "string",
"enum": [
"gzip+base64"
],
"description": "When present, indicates that the `payload` field has been compressed (gzip) and base64-encoded. Absent on raw (uncompressed) payloads.\n"
},
"checksum": {
"type": "string",
"description": "SHA-256 hex digest of the decoded script body, for integrity verification before applying."
}
},
"required": [
"type",
"id",
"payload"
]
}Example
Example 1
{
"type": "script_update",
"id": "upd-2026-06-08-001",
"payload": "-- Lua protocol script\nreturn { pulses = 100, interval_ms = 500 }",
"checksum": "adaeff5386f5e9dcaef58c0cc39f69f2d62a98bedae07195d02bdc82595a90ad"
}