Developers · IOTMP Protocol

One open protocol for everything a device says

IOTMP has carried Thinger.io's device traffic since 2015. Telemetry, remote calls, streams, terminals and tunnels share one TLS connection, and the protocol is now an open IETF Internet-Draft that anyone can implement.

IETF Internet-Draft·PSON·TLS·< 400 lines of C

How it works

One connection, many conversations

Telemetry, cloud calls, firmware and remote access usually ride separate protocols, each with its own port, credential and stack. IOTMP opens one outbound connection and tells the conversations apart with a Stream ID on every frame.

DEVICEIOTMP CLIENTMCU · LINUX GATEWAYONE TLS CONNECTION · OUTBOUND · PORT 25206EVEN STREAM IDS: OPENED BY THE DEVICE · ODD: BY THE SERVER#12 TELEMETRY#13 REMOTE CALL#15 TERMINAL#17 FILES#19 TCP TUNNELSERVERTHINGER.IOOR ANY IMPLEMENTATIONFIVE CONVERSATIONS, ONE SOCKET · EACH STREAM OPENS, RUNS AND CLOSES ON ITS OWN · KEEP_ALIVE CARRIES NO STREAM ID
  • Telemetry#12

    START_STREAM · STREAM_DATA

    Samples at the rate the server asks for. In compact mode the keys travel once.

  • Remote call#13

    RUN · OK

    Either side calls a resource of the other and gets OK or ERROR back.

  • Terminal#15

    STREAM_DATA both ways

    A shell with a PTY, keystrokes down and output up on one stream.

  • Files#17

    RUN · STREAM_DATA

    Small files inline in the reply, large ones in chunks with flow control.

  • TCP tunnel#19

    STREAM_DATA both ways

    TCP relayed to a service on the device LAN: SSH, a PLC, a web panel.

Transport
TLS on port 25206, a WebSocket on 443 where only web traffic gets out, or plain TCP on a trusted network.
Symmetric
After CONNECT both ends expose resources and call each other's. A server can start work on the device without the device polling.
Self-describing
DESCRIBE asks a peer for its API: resources, inputs and outputs, current values and optionally a JSON Schema. Binary on the wire, readable all the same.

On the wire

Ten message types cover the whole protocol

Terminals, file transfers and tunnels add no message type: they are built on the same RUN and STREAM_DATA primitives that carry a temperature reading.

CodeMessageDirWhat it does
Session
0x03CONNECTDevice to serverOpens the session with credentials, a token or a certificate
0x04DISCONNECTEither directionEnds the session cleanly
0x05KEEP_ALIVEEither directionKeeps the connection up; the only frame without a Stream ID
Replies
0x01OKAnswer to a requestThe request succeeded, with a result when there is one
0x02ERRORAnswer to a requestThe request failed; after CONNECT, the server closes
Calls
0x06RUNEither directionCall a resource on the other end with a PSON payload
0x07DESCRIBEEither directionAsk the other end for its API: resources, inputs, outputs, optional JSON Schema
Streams
0x08START_STREAMEither directionOpen a stream on a resource: telemetry, a terminal, a tunnel
0x09STOP_STREAMEither directionClose it from either end
0x0ASTREAM_DATAEither directionA sample, a chunk, a line of output, in the stream
Anatomy of a frameTest vector 15.4.4

RUN the resource led with {"on": true}: a type, a body size and three tagged fields. 15 bytes on the wire.

06TypeRUN
0DBody size13 bytes
08 64Stream ID100
22 83 6C 65 64Resource"led"
1A C1 82 6F 6E 61Payload{"on": true}

2 B KEEP_ALIVE4 B OK without payload15 B this call

Compact streaming

Send the keys once, then only the values

When the server asks for compact mode, the first sample sets the keys and every sample after it carries the values alone, in the same order. Payloads travel as PSON, a binary drop-in for JSON, 40 to 75% smaller on typical IoT data.

First sample · sets the schema38 B

{"temperature": 23.5, "humidity": 60, "pressure": 1013}

Every sample after it10 B

[23.6, 61, 1013]

PSON payload sizes from the compact mode example of the IOTMP draft (11.4.6) · one cell, one byte

60%

Smaller per sample

Temperature and humidity: 35 bytes per sample in normal mode, 14 in compact mode.

67%

With more keys

An eight sensor environmental station: 83 bytes per sample down to 27.

78%

Less than MQTT 3.1.1

For 100 samples of two sensors, and 67% less than MQTT v5 with topic aliases.

Figures from the draft (Tables 25 and 26). ESP32 benchmarks against MQTT, CoAP, LwM2M and HTTP are on iotmp.io.

SPECIFIED DOWN TO THE BYTE

Beyond telemetry

Reach the device, not just its data

The Thinger.io clients build four jobs that usually need a tool of their own on the same RUN and STREAM_DATA primitives, over the connection the device already keeps open.

Resources as a live REST API

Every resource the firmware declares is called with RUN, and the platform exposes it as a REST endpoint: POST to send it a value, GET to read it. No topic conventions, no glue code on either side.

OTA updates and a remote console

Firmware reaches ESP32 and the other supported boards over the connection they already keep open, in chunks with flow control, and the same connection carries a console session to the microcontroller.

Files, inline or in chunks

A config file comes back inline in one RUN reply. Logs and large files stream in chunks with flow control and bandwidth limits, with no FTP server or second protocol on the device.

SSH and web proxies on Linux

A transparent TCP relay to the device itself or to anything on its LAN: SSH, a router panel, a PLC, a database port. No port forwarding, no VPN, nothing exposed to the internet.

ThinRemote turns these channels into a managed service for Linux fleets

Security model

Encrypted, authenticated, outbound only

Every session opens the same way: the device dials out, TLS comes up, the device proves who it is, and only then can either side send.

  1. The device dials out

    OUTBOUND ONLY

    The connection always starts on the device, never from the server. Nothing listens, nothing is forwarded: it works behind NAT and firewalls the way a browser does.

  2. TLS before anything else

    TLS 1.2+ · PORT 25206 · WSS 443

    TLS 1.2 or later is required in production, 1.3 recommended: on port 25206, or over a WebSocket on 443 where only web traffic gets out. Plain TCP is for trusted networks and development.

  3. CONNECT, then talk

    CREDENTIALS · TOKEN · CERTIFICATE

    The first frame proves who the device is: its credentials, a bearer token or a client certificate. On OK either side can send at any time; on ERROR the server closes.

  • No open ports. There is no inbound surface on the device to scan, harden or patch.

  • Behind NAT and firewalls. Factory floors, cellular links and home routers need no change at all.

  • One credential. One identity covers telemetry, calls, terminals, files and tunnels.

Implement it

Four hundred lines of C, or a library that already speaks it

The same sketch that puts an ESP32 online in the quick start is an IOTMP client: the frames of the trace at the top of the page are what these lines send.

esp32.inoThinger.io Arduino client
#include <ThingerESP32.h>ThingerESP32 thing(USERNAME, DEVICE_ID, CREDENTIAL);CONNECTvoid setup() {  pinMode(16, OUTPUT);  thing.add_wifi(SSID, PASSWORD);  thing["relay"] << digitalPin(16);answers RUN  thing["uptime"] >> outputValue(millis());STREAM_DATA}void loop() {  thing.handle();KEEP_ALIVE · reconnect}

Connected · TLS · 1 connection

A good fit

  • Devices that are both controlled and observed over the same connection
  • Constrained links where every byte counts: cellular, satellite, low bandwidth
  • Operations the server starts on the device, without polling
  • Real-time interaction: terminals, proxies, live dashboards
  • Gateways and edge devices on WiFi, Ethernet or cellular

Not a replacement for every protocol

  • MQTTWhen one-to-many broadcast is the main pattern, publish/subscribe fits better.
  • CoAPBattery sensors that wake to send one reading work connectionless over UDP.
  • LPWANA handful of bytes a day over LoRaWAN calls for a purpose-built protocol.
  • LwM2MDeployments bound to existing MQTT or LwM2M infrastructure stay on it.

Thinger.io speaks both sides of that line: MQTT, HTTP, LoRaWAN and Sigfox devices land in the same console as IOTMP ones. See Device Connectivity

Next step

Implement it, or put it to work today

Read the open draft and build your own implementation, or let the open-source Thinger.io clients speak it for you on a free account.