Message Envelopes
FlowLayer V1 messages share one common JSON envelope.
Common structure
{
"type": "<message_type>",
"id": "<correlation_id>",
"name": "<command_or_event_name>",
"payload": {}
}
Envelope fields are omitted when not applicable.
Envelope fields
| Field | Type | Required | Notes |
|---|---|---|---|
type | string | Always | One of command, ack, result, event, error |
id | string | Required for command, ack, result | Correlates command lifecycle; optional on error |
name | string | Required for command, event | Command or event name |
payload | object | Type-dependent | Required shape depends on message type |
Message types
type | Direction | Purpose |
|---|---|---|
command | client -> server | Request an operation |
ack | server -> client | Immediate acceptance/rejection of a command |
result | server -> client | Final outcome of an accepted command |
event | server -> client | Asynchronous runtime notification |
error | server -> client | Protocol-level validation/routing error |
Correlation with id
The same id links one command lifecycle:
- client sends
commandwithid - server sends
ackwith sameid - if
ack.payload.acceptedistrue, server later sendsresultwith sameid
When ack.payload.accepted is false, no result follows for that command.
Minimal examples
command
{
"type": "command",
"id": "cmd-42",
"name": "get_snapshot"
}
ack
{
"type": "ack",
"id": "cmd-42",
"payload": {
"accepted": true
}
}
result
{
"type": "result",
"id": "cmd-42",
"payload": {
"ok": true,
"data": {
"services": []
}
}
}
event
{
"type": "event",
"name": "service_status",
"payload": {
"service": "api",
"status": "running",
"timestamp": "2026-04-25T10:00:00Z"
}
}
error
{
"type": "error",
"payload": {
"code": "invalid_json",
"message": "invalid json message"
}
}
Validation rules
The protocol validator enforces these envelope-level checks:
| Rule | Error code |
|---|---|
| Frame is not valid JSON | invalid_json |
type missing or empty | missing_type |
type is unknown | unknown_type |
id missing on command/ack/result | missing_id |
name missing on command/event | missing_name |
| Invalid required payload shape | invalid_payload |
Type-specific payload checks at validation layer:
ack.payload.acceptedmust be presentresult.payload.okmust be presenterror.payload.codeanderror.payload.messagemust both be present and non-empty
Command-specific payload checks (for example payload.service or payload.limit) are handled by command processing and can also produce invalid_payload.
See Errors for complete code catalog and WebSocket Lifecycle for transport/session sequencing.