Feed data ingestion

After OAuth client credentials authentication, a control device can ingest canonical feed-data events into Realer through the HTTPS iot/v1 feed-data endpoints by providing the returned Bearer access token. The same public contract accepts command acknowledgements and sensor readings through one typed per-item schema.

This page documents HTTPS ingestion. MQTT publishes use the same per-item feed-data schema, with transport-specific delivery and acknowledgement behavior documented in the MQTT device flow. Use field semantics for retry, ordering, desired-state correlation, and result-handling rules.

Command state reports

Realer separates desired command state from reported physical command state. A user or automation changes the desired command state in Realer; the control device reports what physically happened by sending command feed data.

A device should not directly update the command record. If a local physical switch, button, or actuator changes state, send a command feed-data item with the current value, value_received_at, and a unique message_id.

Realer uses that command feed data to update the latest reported state shown in the UI. If the desired state and reported state differ, the UI can show the command as pending or out of sync instead of hiding the difference.

If local reported-state adoption is enabled in the command configuration, a local physical report can intentionally become the new desired value and is considered already executed because it came from the device's physical state. Adoption is disabled by default, applies only to local command reports without desired_id, and is audited by Realer. Without that policy, feed-data reports update reported state only; they do not mutate control_devices_commands.value.

The HTTPS v1 feed-data endpoint uses command_id, value, value_received_at, message_id, optional desired_id, optional report_status, and optional sequence_number. MQTT command acknowledgements use the same meaning for desired_id and report_status when they answer a Realer desired-state message.

  • When Realer sends a desired command and the device applies it, report the resulting physical value with the original desired_id. report_status can be omitted; Realer treats it as applied.
  • When a device refuses a desired command or detects that it is stale, report the current physical value with the original desired_id and report_status set to rejected or stale.
  • When a local physical switch changes state without a Realer desired command, report the physical value without desired_id.
  • When a device reconnects after being offline, send the latest physical state with a new message_id so Realer can reconcile the UI.

Sensor readings

Sensor feed data reports observed physical measurements. Send sensor_id, value, value_received_at, and a stable message_id for each sensor reading.

value_received_at is the time the device observed the measurement, not the time Realer receives it. For retries of the same physical measurement, reuse the same message_id. For a later measurement, use a new message_id.

Sensor readings do not answer desired command state, so omit command-only fields such as desired_id and report_status.

Single-item ingestion

cURL
curl "https://api.therealer.com/iot/v1/devices/12345/feed-data" \
  -X POST \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer b11db7f6c816568eb3b156df3aeaa5' \
  -d '{"command_id":1,"value":"0","value_received_at":"2026-04-24T10:15:00Z","message_id":"cmd-ack-1","sequence_number":42}'
POST /iot/v1/devices/{device_id}/feed-data

Ingest one command acknowledgement or one sensor reading.

Request headers
Authorization
(required)

The Bearer access token obtained from the OAuth token endpoint.

Type: String

Example: Bearer b11db7f6c816568eb3b156df3aeaa5

Content-Type
(required)

The request body media type.

Value: application/json

Path parameters
device_id
(required)

ID (id) of the authenticated control device that is ingesting the event.

Type: Integer

Example: 12345

Request body
JSON
{
  "command_id": 1,
  "value": "0",
  "value_received_at": "2026-04-24T10:15:00Z",
  "message_id": "cmd-ack-1",
  "sequence_number": 42
}
Fields
command_id

Exactly one of command_id or sensor_id is required for each item.

sensor_id

Use for sensor readings instead of command_id.

value

Raw source value to validate through the canonical semantic contract.

value_received_at

Canonical source event time for the submitted value. This is not server receipt time.

message_id

Transport-level idempotency key scoped to the authenticated device and semantic source.

sequence_number

Optional integer source ordering hint for diagnostics and reconciliation. It is not the primary current-state ordering authority.

desired_id

Optional Realer desired-state id when this command report answers a command sent by Realer. Omit it for local physical changes.

report_status

Optional command outcome for reports with desired_id: applied, rejected, or stale. For local physical command reports, omit this field; if sent without desired_id, only reported is valid.

Responses

201 Created

JSON
{
  "code": 2000,
  "status": "created",
  "feed_data_id": 123,
  "message_id": "cmd-ack-1",
  "warnings": []
}

200 OK idempotent replay

JSON
{
  "code": 2000,
  "status": "idempotent",
  "feed_data_id": 123,
  "message_id": "cmd-ack-1",
  "warnings": []
}

422 Unprocessable Content

Validation failure

JSON
{
  "code": 4022,
  "error": {
    "type": "validation_failed",
    "message": "feed data ingestion failed",
    "details": {
      "command_id": ["is invalid for this device"]
    }
  },
  "request_id": "..."
}
The feed-data contract does not use a top-level feed_data wrapper. Top-level commands and sensors arrays belong to the device catalog contract.

Batch ingestion

cURL
curl "https://api.therealer.com/iot/v1/devices/12345/feed-data/batches" \
  -X POST \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer b11db7f6c816568eb3b156df3aeaa5' \
  -d '{"items":[{"command_id":1,"value":"0","value_received_at":"2026-04-24T10:15:00Z","message_id":"cmd-ack-1"},{"sensor_id":2,"value":"18.49","value_received_at":"2026-04-24T10:15:02Z","message_id":"sensor-2-reading-1"}]}'
POST /iot/v1/devices/{device_id}/feed-data/batches

Ingest multiple feed-data items in one request. The request body must be an explicit items envelope. For a valid batch envelope, the server returns ordered per-item outcomes even when results are mixed.

Request headers
Authorization
(required)

The Bearer access token obtained from the OAuth token endpoint.

Type: String

Example: Bearer b11db7f6c816568eb3b156df3aeaa5

Content-Type
(required)

The request body media type.

Value: application/json

Path parameters
device_id
(required)

ID (id) of the authenticated control device that is ingesting the event.

Type: Integer

Example: 12345

Request body
JSON
{
  "items": [
    {
      "command_id": 1,
      "value": "0",
      "value_received_at": "2026-04-24T10:15:00Z",
      "message_id": "cmd-ack-1"
    },
    {
      "sensor_id": 2,
      "value": "18.49",
      "value_received_at": "2026-04-24T10:15:02Z",
      "message_id": "sensor-2-reading-1"
    }
  ]
}
Responses

200 OK

JSON
{
  "code": 2000,
  "status": "processed",
  "results": [
    {
      "item_index": 0,
      "code": 2000,
      "status": "created",
      "feed_data_id": 123,
      "message_id": "cmd-ack-1",
      "warnings": []
    },
    {
      "item_index": 1,
      "code": 2000,
      "status": "created",
      "feed_data_id": 124,
      "message_id": "sensor-2-reading-1",
      "warnings": []
    }
  ]
}
Batch items are evaluated in request order. A same-batch duplicate with the same payload becomes idempotent; a same-batch duplicate with a different payload becomes conflict.

Firmware rules

  • Keep message_id stable across retries of the same local event.
  • Use a new message_id only for a new physical event or intentionally new reconciliation report.
  • Use sequence_number for diagnostics and local ordering hints, not as the primary idempotency key.
  • For application behavior, check the response code, status, and any error.type documented in response codes.