Connect

Configure HTTP endpoints and MQTT connectors to ingest events into your workspace.

The Connect tab is where you manage every inbound data channel for your workspace.

HTTP endpoints

A workspace can have multiple HTTP endpoints. Each endpoint has its own URL and authentication settings, letting you segment producers by access policy or environment.

Endpoint URL

Each endpoint is served at https://iotman.io/data/<workspace-slug>/<url_path>. The url_path defaults to a slug derived from the endpoint name and can be renamed in the edit form.

When Read access is enabled the endpoint also appears on the Export tab as a Processed endpoint backed by a passthrough transformation. GET on the URL returns paginated data, the same URL with /stream appended upgrades to a WebSocket live stream, and you can attach webhooks from the Export tab. Toggling read off removes the export endpoint; the underlying tag rule and output stay in place so you can re-enable read without losing what you tagged.

Creating an endpoint

  1. Click + New endpoint.
  2. Enter a name. The URL path is derived from the name automatically (e.g. "Field Sensors" → field-sensors). You can also enter a custom URL path.
  3. Choose an authentication method (see below).
  4. Click Create. The endpoint URL is shown immediately.

Requires Editor or Admin role.

Changing the URL path

Open the edit form for an endpoint and update the URL path field. The path must be 1–64 characters and may only contain lowercase letters, digits, hyphens, and underscores. It must be unique within the workspace.

Note: Changing the URL path will break any producer or integration using the old URL.

Authentication

MethodDescription
NonePublic. Any producer with the URL can POST.
OAuth2Sender presents a Bearer token issued by an OAuth2 client registered in Access.

OAuth2

Register an OAuth2 client in the Access tab, then select it when creating the endpoint. The sender must include a valid Bearer token on every POST: Authorization: Bearer <token>.

Two client types are supported:

In both cases IoTMan identifies the sender from the token, enabling per-client or per-user data attribution.

Sending data

POST https://iotman.io/data/<workspace>/<endpoint>
Content-Type: application/json

{"sensor":"s1","value":22.4,"ts":1710000000}

Any valid JSON payload is accepted by default. The response is {"status":"success"} on success.

Payload schema and validation

Each endpoint is backed by a Source row that carries an optional JSON Schema and an enforcement mode. Open the Schema panel on an endpoint row to declare what conforming payloads look like.

ModeBehavior
off (default)The schema is ignored. Ingest accepts any JSON.
warnIngest accepts the payload. When violations are present, the response body carries a schema_violations array and the X-IotMan-Schema-Violations header reports the count. The violations are also stamped under metadata.schema_violations on the stored row.
rejectNon-conforming payloads are refused with HTTP 422 and a JSON body listing each violation. The row is not stored.

The schema is a JSON Schema document (draft 2020-12 compatible). Use {} to clear constraints. Each save bumps schema_version automatically; the compiled validator is cached per (source_id, schema_version).

The same schema and mode apply to the matching MQTT source: rejected MQTT messages are dropped with a warn log entry; warn-mode MQTT messages are stored with metadata.schema_violations (there is no response channel for the producer).

Response shapes

Conforming payload (any mode):

{ "status": "success", "message": "Data received" }

Non-conforming payload under warn (HTTP 200, X-IotMan-Schema-Violations: 2):

{
  "status": "success",
  "message": "Data received",
  "schema_violations": [
    {
      "instance_path": "/humidity",
      "schema_path": "/properties/humidity/type",
      "message": "\"wet\" is not of type \"number\""
    },
    {
      "instance_path": "/temperature",
      "schema_path": "/properties/temperature/type",
      "message": "\"hot\" is not of type \"number\""
    }
  ]
}

Non-conforming payload under reject (HTTP 422):

{
  "error": "payload does not conform to source schema",
  "schema_violations": [
    {
      "instance_path": "",
      "schema_path": "/required",
      "message": "\"humidity\" is a required property"
    }
  ]
}

The schema_violations shape is identical across both modes so a producer can handle observation and enforcement with one parser. The X-IotMan-Schema-Violations header is only set when violations are present, so cheap log scraping (grep on the header) flags warn-mode anomalies without parsing the body.

Removing an endpoint

Click the delete icon on an endpoint row. The URL stops accepting requests immediately. Data already ingested is retained.

Requires Editor or Admin role.

MQTT connectors

IoTMan can subscribe to topics on your existing MQTT brokers and ingest messages automatically.

Adding a connector

  1. Click + Add connector.
  2. Fill in the broker host and port, topic filter, and optionally a username and password.
  3. Click Save. The connector starts immediately.

Requires Editor or Admin role.

Connection behavior

IoTMan connects with a durable session and a stable client identifier per connector. When the connection drops and is re-established, the broker restores the existing subscription, so an interrupted connector resumes ingesting on its own.

Messages your publishers send at QoS 1 or 2 while IoTMan is disconnected are queued by the broker and delivered on reconnect. Messages published at QoS 0 are not queued by any broker and are lost for the duration of a disconnection.

Brokers replay retained messages whenever a subscription is created. IoTMan subscribes only when the broker reports that it holds no session for the connector, so an ordinary reconnect does not re-deliver retained messages. If the broker itself loses the session, for example a restart with persistence disabled, IoTMan re-subscribes and any retained messages are ingested again as new events.

Editing a connector

Changing the topic, broker host, port, or credentials rebuilds the connection: IoTMan disconnects, discards the broker session, and reconnects with the new settings, which subscribes to the new topic and delivers any retained messages on it. This happens within one configuration poll, without pausing and resuming.

Renaming a connector does not reconnect it, since the name has no effect on what it subscribes to.

Connection status

Each connector reports what its connection is doing, so a connector that has silently stopped receiving can be told apart from one whose devices simply have nothing to send.

FieldMeaning
connectedThe broker acknowledged the connection and it has not failed since
last_connected_atWhen that acknowledgement arrived
last_message_atWhen a message last arrived on this connector
last_error / last_error_atThe most recent connection failure, cleared once it reconnects
tracking_sinceWhen the running process started observing

This state describes a live connection and is not persisted, so it resets when IoTMan restarts. tracking_since is reported alongside it: a last_message_at of null means nothing has arrived since that moment, which is not the same as nothing ever having arrived.

A connector whose last_message_at falls far behind its usual interval while others keep moving is the signal worth alerting on.

Pausing and resuming

Toggle the switch on any connector row to pause or resume ingestion without deleting the configuration.

While a connector is paused its broker session remains, so the broker continues queuing QoS 1 and 2 messages for it up to whatever queue limit the broker enforces. Resuming delivers that backlog.

Deleting a connector

Click the delete icon. Data already ingested is retained.

Deleting a connector also clears its session on the broker, so the broker stops holding a subscription and queuing messages for it. If the broker is unreachable at that moment the session is left in place, and IoTMan records a warning naming the client identifier so you can clear it on the broker yourself.

Requires Editor or Admin role.