Sign in

← All schemas

Schema · sensors/ingest

Sensor ingest request

The body a producer posts to Ingest (POST /v1/atlas/signals, proto iohr.sensors.v1.IngestRequest): readings from one sensor, at most 500, each accepted or refused on its own (send an Idempotency-Key header to make a retry safe). A reading is a produced_at, exactly one of a number (value) or a state word (state), labels from the sensor's label_keys, and optionally the digest of evidence the producer keeps. It carries no content: no text, prompt, document or credential, and every object is closed so a field outside these is refused. Only the sensor's producer may write, a paused or revoked sensor refuses, and a built-in sensor is read only: the service decides those, the schema cannot. Draft line: it may still be corrected.

Canonical $id, draft
https://schemas.inorbit.hr/sensors/ingest/v0.json
01Versions

Each version is a file at its own address. The raw file is plain JSON, served without a sign-in.

02Fields

Fields of v0, the newest version, by path. A name ending in [] is each item of a list. Every field not listed is refused.

  • sensor_idstringrequired

    The sensor to write to: sen_ and a ULID (the id Register answered). Never a bare UUID.

    pattern ^sen_[0-9A-HJKMNP-TV-Z]{26}$at most 30 characters

  • schema_versionintegeroptional

    The schema version the producer speaks, 1 to 1000. It must equal the sensor's own schema_version (Register set it; 1 today); leave it out to send under the sensor's.

    1 to 1000

  • account_idstringoptional

    The account to write into, a UUID. Leave it out for the caller's own; only a service names another account.

    pattern ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$at most 36 characters

  • readingslist of anyrequired

    The batch: 1 to 500 readings, in the order sent (the answer's outcomes follow it).

    at most 500 items

03Examples

Valid documents with made-up values, as the repository's tests check them.

{
  "sensor_id": "sen_01JC3Z8Q4M7T2V9XK5R6B1N0HA",
  "readings": [
    {
      "produced_at": "2026-10-23T14:09:26.123Z",
      "value": 182.5,
      "labels": {
        "volume": "/"
      }
    },
    {
      "produced_at": "2026-10-23T14:10:26Z",
      "value": 181.9
    }
  ],
  "schema_version": 1
}

The repository's tests also check 45 documents that this schema must refuse.

04Check a file against it

Replace the file name with yours.

VS Code, JetBrains: settings
"json.schemas": [
  { "fileMatch": ["my-file.json"], "url": "https://schemas.inorbit.hr/sensors/ingest/v0.json" }
]
check-jsonschema
check-jsonschema --schemafile https://schemas.inorbit.hr/sensors/ingest/v0.json my-file.json
ajv-cli
ajv validate --spec=draft2020 -s <(curl -s https://schemas.inorbit.hr/sensors/ingest/v0.json) -d my-file.json
curl
curl -s https://schemas.inorbit.hr/sensors/ingest/v0.json
05The schema itself

The raw file of v0, as published.

schemas.inorbit.hr/sensors/ingest/v0.json
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://schemas.inorbit.hr/sensors/ingest/v0.json",
  "title": "Sensor ingest request",
  "description": "The body a producer posts to Ingest (POST /v1/atlas/signals, proto iohr.sensors.v1.IngestRequest): readings from one sensor, at most 500, each accepted or refused on its own (send an Idempotency-Key header to make a retry safe). A reading is a produced_at, exactly one of a number (value) or a state word (state), labels from the sensor's label_keys, and optionally the digest of evidence the producer keeps. It carries no content: no text, prompt, document or credential, and every object is closed so a field outside these is refused. Only the sensor's producer may write, a paused or revoked sensor refuses, and a built-in sensor is read only: the service decides those, the schema cannot. Draft line: it may still be corrected.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "sensor_id",
    "readings"
  ],
  "properties": {
    "sensor_id": {
      "description": "The sensor to write to: sen_ and a ULID (the id Register answered). Never a bare UUID.",
      "type": "string",
      "maxLength": 30,
      "pattern": "^sen_[0-9A-HJKMNP-TV-Z]{26}$"
    },
    "schema_version": {
      "description": "The schema version the producer speaks, 1 to 1000. It must equal the sensor's own schema_version (Register set it; 1 today); leave it out to send under the sensor's.",
      "type": "integer",
      "minimum": 1,
      "maximum": 1000
    },
    "account_id": {
      "description": "The account to write into, a UUID. Leave it out for the caller's own; only a service names another account.",
      "type": "string",
      "maxLength": 36,
      "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
    },
    "readings": {
      "description": "The batch: 1 to 500 readings, in the order sent (the answer's outcomes follow it).",
      "type": "array",
      "minItems": 1,
      "maxItems": 500,
      "items": {
        "$ref": "#/$defs/reading"
      }
    }
  },
  "$defs": {
    "reading": {
      "description": "One reading as the producer sends it (proto iohr.sensors.v1.SignalReading). A gauge sends a value, a counter a value of zero or more, a state sensor a state: the service checks the kind. The producer's time may not be more than a day ahead or 7 days old (the service refuses with future or too_old).",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "produced_at"
      ],
      "properties": {
        "produced_at": {
          "description": "RFC 3339, the producer's clock.",
          "$ref": "https://schemas.inorbit.hr/sensors/reading/v0.json#/$defs/timestamp"
        },
        "value": {
          "description": "A gauge's or counter's value: a finite number.",
          "type": "number"
        },
        "state": {
          "description": "A state sensor's value: 1 to 32 of a-z, 0-9 and underscore.",
          "$ref": "https://schemas.inorbit.hr/sensors/reading/v0.json#/$defs/state_word"
        },
        "labels": {
          "description": "At most 8, keys from the sensor's label_keys, each value 1 to 64 characters.",
          "$ref": "https://schemas.inorbit.hr/sensors/reading/v0.json#/$defs/labels"
        },
        "evidence_digest": {
          "description": "Optional: sha256: and 64 lowercase hex characters, of evidence the producer keeps. Leave it out when there is none.",
          "$ref": "https://schemas.inorbit.hr/sensors/reading/v0.json#/$defs/evidence_digest"
        }
      },
      "oneOf": [
        {
          "required": [
            "value"
          ]
        },
        {
          "required": [
            "state"
          ]
        }
      ]
    }
  }
}