Message Reference
This page is the normative byte-level reference for all Zenoh messages.
For primitive encoding types (z8, z32, VLE, ZenohID, etc.) see Wire Primitives.
Scouting messages are specified in Scouting.
Message ID Ranges
Transport message IDs occupy 0x00–0x07; network message IDs occupy 0x19–0x1F.
These ranges are deliberately non-overlapping so that a receiver can identify the layer without additional context.
Data sub-message IDs (0x01–0x05) are scoped to the body of the enclosing PUSH, REQUEST, or RESPONSE message.
Transport Messages
Transport messages handle session establishment, lease management, reliable delivery, and message batching. They are exchanged directly over the underlying link before network-layer messages can flow.
On stream-oriented transports (TCP) each transport message is preceded by a 2-byte little-endian length prefix (see Stream Framing).
| Message | ID (dec) | ID (hex) | Scope |
|---|---|---|---|
OAM |
0 |
0x00 |
Both |
INIT |
1 |
0x01 |
Unicast only |
OPEN |
2 |
0x02 |
Unicast only |
CLOSE |
3 |
0x03 |
Both |
KEEP_ALIVE |
4 |
0x04 |
Both |
FRAME |
5 |
0x05 |
Both |
FRAGMENT |
6 |
0x06 |
Both |
JOIN |
7 |
0x07 |
Multicast only |
OAM — Transport Operations / Administration / Management (0x00)
Transport OAM carries transport-scoped management payloads.
The header uses the standard extension encoding bits to select whether the OAM body is Unit, Z64, or ZBuf.
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |Z|ENC| OAM | ID = 0x00 +-+-+-+---------+ % id : z16 % OAM identifier +---------------+ ~ [oam_exts] ~ if Z==1 +---------------+ ~ body ~ body encoding selected by ENC +---------------+
Transport OAM extensions:
| Ext ID | Type | M | Extension |
|---|---|---|---|
0x1 |
Z64 |
Y |
QoS priority lane for this OAM message |
INIT — Session Initialisation (0x01)
INIT is exchanged as a SYN/ACK pair to negotiate session parameters. See Session Establishment (INIT & OPEN) for the full handshake flow.
Flags: A (Ack, bit 5) — 0 = InitSyn, 1 = InitAck; S (Size, bit 6) — resolution + batch_size fields present; Z (bit 7) — extensions follow.
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |Z|S|A| INIT | ID = 0x01 +-+-+-+---------+ | version | Protocol version (u8); current = 0x09 +---------------+ |zid_len|X|X|WAI| Packed byte: bits 7:4 = zid_len, bits 1:0 = WhatAmI +-+-+-+-+-+-+-+-+ ~ ZID ~ (1 + zid_len) bytes +---------------+ |X|X|X|X|RID|FSN| if S==1: Resolution byte +---------------+ | batch_lo | if S==1: Batch size (u16 LE) +---------------+ | batch_hi | +---------------+ ~ <u8;z16> ~ Cookie — InitAck (A==1) ONLY +---------------+ ~ [InitExts] ~ if Z==1 +---------------+
OPEN — Link Finalisation (0x02)
OPEN finalises the transport link after a successful INIT exchange. See Session Establishment (INIT & OPEN).
Flags: A (Ack, bit 5); T (Time unit, bit 6) — 1 = lease in seconds, 0 = milliseconds; Z (bit 7).
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |Z|T|A| OPEN | ID = 0x02 +-+-+-+---------+ % lease % VLE-encoded lease duration (unit per T flag) +---------------+ % initial_sn % VLE-encoded initial sequence number +---------------+ ~ <u8;z16> ~ Cookie (OpenSyn, A==0 only) — MUST match cookie from InitAck +---------------+ ~ [OpenExts] ~ if Z==1 +---------------+
initial_sn MUST fall within the range of the negotiated SN resolution.
CLOSE — Session/Link Termination (0x03)
See Close.
Flags: S (Session, bit 5) — 1 = close whole session, 0 = close this link only; Z (bit 7).
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |Z|X|S| CLOSE | ID = 0x03 +-+-+-+---------+ | reason | Close reason code (u8); see xref:session:close.adoc[] +---------------+ ~ [CloseExts] ~ if Z==1 +---------------+
KEEP_ALIVE — Lease Renewal (0x04)
See Keep-Alive.
Flags: Z (bit 7) only.
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |Z|X|X| KALIVE | ID = 0x04 +-+-+-+---------+ ~ [KAliveExts] ~ if Z==1 +---------------+
No mandatory body fields.
FRAME — Network Message Container (0x05)
FRAME batches one or more complete, serialised NetworkMessages. See Batching.
Flags: R (Reliable, bit 5) — 1 = reliable channel; Z (bit 7).
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |Z|X|R| FRAME | ID = 0x05 +-+-+-+---------+ % seq_num % VLE-encoded sequence number (resolution-dependent) +---------------+ ~ [FrameExts] ~ if Z==1 +---------------+ ~ [NetworkMsg] ~ one or more back-to-back serialised NetworkMessages (*) +---------------+
(*) NetworkMessages fill the remainder of the batch; each is self-delimiting.
Frame QoS Extension (Z64, ID=0x1, M=true):
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |0| reserved | bits 7:3 — reserved (zero) | priority | bits 2:0 — priority class (0=Control … 7=Background) +-+-+-+---------+
FRAGMENT — Large Message Fragment (0x06)
See Fragmentation.
Flags: R (Reliable, bit 5); M (More, bit 6) — 1 = more fragments follow, 0 = last fragment; Z (bit 7).
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |Z|M|R| FRAGMENT| ID = 0x06 +-+-+-+---------+ % seq_num % VLE-encoded sequence number (same space as FRAME on this channel) +---------------+ ~ [FragExts] ~ if Z==1 +---------------+ ~ [fragment] ~ raw fragment bytes (remainder of the batch) +---------------+
JOIN — Multicast Capability Advertisement (0x07)
JOIN is sent periodically on multicast transports to advertise session parameters. No handshake is required; any node that receives a JOIN can immediately send network messages to that peer. See JOIN.
Flags: T (Time unit, bit 5); S (Size, bit 6); Z (bit 7).
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |Z|S|T| JOIN | ID = 0x07 +-+-+-+---------+ | version | Protocol version (u8). Current: 0x09 +---------------+ |zid_len|X|X|WAI| Packed byte (same layout as INIT) +-+-+-+-+-+-+-+-+ ~ ZID ~ (1 + zid_len) bytes +---------------+ |X|X|X|X|RID|FSN| if S==1: Resolution byte +---------------+ | batch_lo | if S==1: Batch size (u16 LE) +---------------+ | batch_hi | +---------------+ % lease % VLE-encoded lease duration (unit per T flag) +---------------+ % next_sn_re % VLE-encoded next reliable SN (default/non-QoS channel) +---------------+ % next_sn_be % VLE-encoded next best-effort SN (default channel) +---------------+ ~ [JoinExts] ~ if Z==1 +---------------+
When the QoS extension is present, per-priority SNs in the extension supersede the body SNs for their respective priorities.
Network Messages
Network messages carry application-layer semantics. On the default transport they are serialised inside Transport FRAME or FRAGMENT payloads. On negotiated low-latency unicast sessions, implementations may serialize a network message directly using the reduced transport codec described in Frame Format.
| Message | ID (dec) | ID (hex) | Purpose |
|---|---|---|---|
INTEREST |
25 |
0x19 |
Request current/future declarations from a peer |
RESPONSE_FINAL |
26 |
0x1A |
Signal end of replies for a request |
RESPONSE |
27 |
0x1B |
Carry one reply to a REQUEST |
REQUEST |
28 |
0x1C |
Query a key expression |
PUSH |
29 |
0x1D |
Publish data or deletion to a key expression |
DECLARE |
30 |
0x1E |
Announce or retract resources (subscribers, queryables, etc.) |
OAM |
31 |
0x1F |
Operations, administration, and management payload |
OAM (0x1F)
Network OAM carries management payloads scoped to the network-message layer.
As with transport OAM, the header encoding bits select whether the body is Unit, Z64, or ZBuf.
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |Z|ENC| OAM | ID = 0x1F +-+-+-+---------+ % id : z16 % OAM identifier +---------------+ ~ [oam_exts] ~ if Z==1 +---------------+ ~ body ~ body encoding selected by ENC +---------------+
Network OAM extensions:
| Ext ID | Type | M | Extension |
|---|---|---|---|
0x1 |
Z64 |
N |
QoS |
0x2 |
ZBuf |
N |
Timestamp |
Common Network Extensions
The following extensions appear on multiple network messages with the same Ext IDs.
QoS Extension (Z64, ID=0x1, M=false)
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |0|r|F|E|D|prio | encoded as the low byte of the z64 value +-+-+-+-+-------+
| Sub-field | Bits | Meaning |
|---|---|---|
|
2:0 |
Priority class (0–7; default = 5 = Data) |
|
3 |
Don’t-drop — use Block congestion control |
|
4 |
Express — disable message batching for this message |
|
5 |
Don’t-drop-first — BlockFirst mode (Patch ≥ 1) |
|
6 |
Reserved (zero) |
7 |
Reserved (zero) |
Priority values:
| Value | Name |
|---|---|
0 |
Control |
1 |
RealTime |
2 |
InteractiveHigh |
3 |
InteractiveLow |
4 |
DataHigh |
5 |
Data (default) |
6 |
DataLow |
7 |
Background |
Congestion control interpretation:
-
D=0, F=0→ Drop (default for PUSH; messages may be lost under congestion) -
D=1, F=0→ Block (default for REQUEST, DECLARE, INTEREST; sender blocks until space available) -
D=0, F=1→ BlockFirst (first message blocks; subsequent messages dropped; requires Patch ≥ 1)
Timestamp Extension (ZBuf, ID=0x2, M=false)
ZBuf payload is a Timestamp primitive (see primitives.adoc#timestamp).
PUSH (0x1D)
Flags: N (Named, bit 5); M (Mapping, bit 6); Z (bit 7).
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |Z|M|N| PUSH | ID = 0x1D +-+-+-+---------+ % key_scope:z16 % VLE ExprId (0 = global scope) +---------------+ ~ key_suffix ~ if N==1: <u8;z16> suffix string +---------------+ ~ [push_exts] ~ if Z==1 (QoS, Timestamp, NodeId) +---------------+ ~ PushBody ~ PUT (0x01) or DEL (0x02) sub-message +---------------+
REQUEST (0x1C)
Flags: N (Named, bit 5); M (Mapping, bit 6); Z (bit 7).
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |Z|M|N| Request | ID = 0x1C +-+-+-+---------+ % request_id:z32% VLE request identifier +---------------+ % key_scope:z16 % VLE ExprId +---------------+ ~ key_suffix ~ if N==1: <u8;z16> +---------------+ ~ [req_exts] ~ if Z==1 (QoS, Timestamp, NodeId, QueryTarget, Budget, Timeout) +---------------+ ~ RequestBody ~ QUERY (0x03) sub-message +---------------+
RESPONSE (0x1B)
Flags: N (Named, bit 5); M (Mapping, bit 6); Z (bit 7).
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |Z|M|N| Response| ID = 0x1B +-+-+-+---------+ % request_id:z32% VLE — correlates to the originating REQUEST +---------------+ % key_scope:z16 % +---------------+ ~ key_suffix ~ if N==1: <u8;z16> +---------------+ ~ [reply_exts] ~ if Z==1 (QoS, Timestamp, ResponderId) +---------------+ ~ ResponseBody ~ REPLY (0x04) or ERR (0x05) sub-message +---------------+
ResponderId Extension (ZBuf, ID=0x3, M=false):
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |zid_len|X|X|X|X| bits 7:4 = encoded ZID length +-+-+-+-+-+-+-+-+ ~ ZID ~ (1 + zid_len) bytes — responder ZenohID +---------------+ % eid : z32 % Entity ID within the responding node +---------------+
RESPONSE_FINAL (0x1A)
Signals that all responses to a given REQUEST have been sent. Exactly one RESPONSE_FINAL is emitted per REQUEST (from each independent source).
Flags: Z (bit 7) only.
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |Z|X|X| ResFinal| ID = 0x1A +-+-+-+---------+ % request_id:z32% VLE — must match the originating REQUEST +---------------+ ~ [rf_exts] ~ if Z==1 (QoS, Timestamp) +---------------+
DECLARE (0x1E)
Carries a single declaration sub-message. See Declarations.
Flags: I (Interest, bit 5) — interest_id field present; Z (bit 7).
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |Z|X|I| DECLARE | ID = 0x1E +-+-+-+---------+ %interest_id:z32% if I==1: VLE interest ID this declare responds to +---------------+ ~ [decl_exts] ~ if Z==1 (QoS, Timestamp, NodeId) +---------------+ ~ declaration ~ DeclareBody sub-message (see xref:session:declarations.adoc[]) +---------------+
INTEREST (0x19)
Requests that a peer send current and/or future declarations. See Interests.
Flags: Mod[0] (bit 5), Mod[1] (bit 6) — 2-bit interest mode; Z (bit 7).
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |Z|Mod| INTEREST| ID = 0x19; Mod in bits 6:5 +-+-+-+---------+ % id : z32 % VLE — Interest identifier +---------------+ |A|M|N|R|T|Q|S|K| Options byte (present only when Mod != Final=0b00) +---------------+ % key_scope:z16 % if Mod!=Final && R==1: VLE ExprId +---------------+ ~ key_suffix ~ if Mod!=Final && R==1 && N==1: <u8;z16> +---------------+ ~ [int_exts] ~ if Z==1 (QoS, Timestamp, NodeId) +---------------+
Data Sub-Messages
Data sub-messages are the innermost payloads of PUSH, REQUEST, and RESPONSE.
| Message | ID | Carried in | Purpose |
|---|---|---|---|
PUT |
0x01 |
PUSH, REPLY |
Publish a value |
DEL |
0x02 |
PUSH, REPLY |
Delete a resource |
QUERY |
0x03 |
REQUEST |
Describe query semantics |
REPLY |
0x04 |
RESPONSE |
Successful query reply (wraps PUT or DEL) |
ERR |
0x05 |
RESPONSE |
Error reply |
Full wire formats are in Push (PUSH / PUT / DEL), Query (REQUEST / QUERY), and Reply (RESPONSE / RESPONSE_FINAL / REPLY / ERR).
PUT (0x01)
Flags: T (Timestamp, bit 5); E (Encoding, bit 6); Z (bit 7).
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |Z|E|T| PUT | ID = 0x01 +-+-+-+---------+ ~ ts: <u8;z16> ~ if T==1: Timestamp +---------------+ ~ encoding ~ if E==1: Encoding field (z32 with S-bit + optional schema) +---------------+ ~ [put_exts] ~ if Z==1 (SourceInfo, Shm, Attachment) +---------------+ ~ pl: <u8;z32> ~ Payload bytes +---------------+
DEL (0x02)
Flags: T (Timestamp, bit 5); Z (bit 7).
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |Z|X|T| DEL | ID = 0x02 +-+-+-+---------+ ~ ts: <u8;z16> ~ if T==1: Timestamp +---------------+ ~ [del_exts] ~ if Z==1 (SourceInfo, Attachment) +---------------+
DEL carries no payload.
QUERY (0x03)
Flags: C (Consolidation, bit 5); P (Parameters, bit 6); Z (bit 7).
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |Z|P|C| QUERY | ID = 0x03 +-+-+-+---------+ |consolidation | if C==1: ConsolidationMode (u8) +---------------+ ~ ps: <u8;z16> ~ if P==1: query parameters (UTF-8) +---------------+ ~ [qry_exts] ~ if Z==1 (SourceInfo, QueryBody, Attachment) +---------------+
REPLY (0x04)
Flags: C (Consolidation, bit 5); Z (bit 7).
7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+ |Z|X|C| REPLY | ID = 0x04 +-+-+-+---------+ |consolidation | if C==1: ConsolidationMode (u8) +---------------+ ~ [repl_exts] ~ if Z==1 +---------------+ ~ ReplyBody ~ PushBody: PUT (0x01) or DEL (0x02) +---------------+
Attachment and QueryBody Notes
Attachment-
On the wire, Attachment extensions are carried as opaque
ZBufvalues. Implementations may choose to encode structured metadata inside that buffer, but the protocol layer itself does not impose a key/value schema. QueryBody-
The QUERY body extension is a
ValueTypepayload at extension ID0x03. When shared-memory support is enabled, its optional SHM marker is encoded as the secondary extension ID0x04inside thatValueType, rather than as an unrelated top-level QUERY extension.