> ## Documentation Index
> Fetch the complete documentation index at: https://api-docs.rhombus.community/llms.txt
> Use this file to discover all available pages before exploring further.

# STOMP Protocol Reference

> Reference for the STOMP 1.2 messaging protocol used by Rhombus WebSocket — frame structure, headers, CONNECT, SUBSCRIBE, MESSAGE, and ERROR command details.

Rhombus uses **STOMP 1.2** (Streaming Text Oriented Messaging Protocol) over WebSocket for real-time event delivery. This page is a protocol reference for developers who need to understand or implement the STOMP framing at a low level.

## What is STOMP?

STOMP is a simple, text-based messaging protocol that provides an interoperable wire format for message brokers. It defines a small set of commands (frames) for connecting, subscribing, sending, and disconnecting. Rhombus uses STOMP because it provides structured pub/sub messaging over a standard WebSocket transport.

## Frame Format

Every STOMP frame follows this structure:

```text theme={null}
COMMAND\n
header-key:header-value\n
header-key:header-value\n
\n
body (optional)
\x00
```

* **COMMAND**: A single word identifying the frame type (e.g., `CONNECT`, `MESSAGE`)
* **Headers**: Zero or more `key:value` pairs, one per line
* **Empty line**: Separates headers from body
* **Body**: Optional payload (typically JSON for MESSAGE frames)
* **Null byte** (`\x00`): Terminates every frame

### Example: Raw CONNECT Frame

```text theme={null}
CONNECT\n
accept-version:1.2\n
heart-beat:10000,10000\n
\n
\x00
```

## Client-to-Server Frames

### CONNECT

Initiates the STOMP session after the WebSocket connection is open.

| Header | Required | Value | Description |
| - | - | - | - |
| `accept-version` | Yes | `1.2` | STOMP protocol version |
| `heart-beat` | Yes | `10000,10000` | Client send interval and desired receive interval (ms) |

```text theme={null}
CONNECT
accept-version:1.2
heart-beat:10000,10000

\x00
```

### SUBSCRIBE

Subscribes to a destination topic to receive messages.

| Header | Required | Value | Description |
| - | - | - | - |
| `id` | Yes | `sub-0` | Client-defined subscription identifier |
| `destination` | Yes | `/topic/change/{orgUuid}` | Topic path to subscribe to |

```text theme={null}
SUBSCRIBE
id:sub-0
destination:/topic/change/a1b2c3d4-e5f6-7890-abcd-ef1234567890

\x00
```

<Note>
  The subscription `id` is client-defined. Use any unique string. If you create multiple subscriptions, each must have a distinct `id`.
</Note>

### DISCONNECT

Signals an intentional, clean disconnection.

```text theme={null}
DISCONNECT

\x00
```

No headers or body are required. After sending DISCONNECT, close the underlying WebSocket connection.

## Server-to-Client Frames

### CONNECTED

Sent by the server in response to a successful CONNECT.

| Header | Value | Description |
| - | - | - |
| `version` | `1.2` | Negotiated STOMP version |
| `heart-beat` | `10000,10000` | Server send/receive heartbeat intervals |

```text theme={null}
CONNECTED
version:1.2
heart-beat:10000,10000

\x00
```

### MESSAGE

Delivers an event from a subscribed topic.

| Header | Value | Description |
| - | - | - |
| `destination` | `/topic/change/{orgUuid}` | The topic this message belongs to |
| `message-id` | Server-generated | Unique message identifier |
| `subscription` | `sub-0` | Matches the subscription `id` |

```text theme={null}
MESSAGE
destination:/topic/change/a1b2c3d4-e5f6-7890-abcd-ef1234567890
message-id:msg-001
subscription:sub-0

{"entity":"POLICY_ALERT","entityUuid":"x1y2z3","type":"CREATE"}
\x00
```

The body is always a JSON object containing the event payload.

## Heartbeats

Heartbeats keep the connection alive and detect failures. They are negotiated during the CONNECT/CONNECTED exchange.

### Format

A heartbeat is a single newline character:

```text theme={null}
\n
```

No command, no headers, no null terminator. Just `\n`.

### Negotiation

The `heart-beat` header uses the format `cx,cy` where:

* `cx` = minimum interval (ms) at which the client can send heartbeats
* `cy` = desired interval (ms) at which the client wants to receive heartbeats

The Rhombus server uses `10000,10000` (10 seconds both directions).

### Behavior

| Direction | Interval | What Happens on Failure |
| - | - | - |
| Client to Server | 10 seconds | Server may close the connection |
| Server to Client | 10 seconds | Client should assume the connection is dead and reconnect |

### Implementation

```python theme={null}
# Sending heartbeats
import threading

def send_heartbeats(ws, stop_event, interval=10):
    while not stop_event.is_set():
        ws.send("\n")
        stop_event.wait(interval)

# Receiving heartbeats
def parse_frame(raw):
    raw = raw.strip("\n\r")
    if not raw or raw == "\x00":
        return None  # This is a heartbeat, safe to ignore
    # ... parse as normal STOMP frame
```

## Frame Parsing Guide

### Step-by-Step Parsing Algorithm

```text theme={null}
1. Read WebSocket text message
2. Strip leading newlines/carriage returns
3. If empty or just \x00 → heartbeat, return null
4. Strip trailing \x00
5. Split on "\n\n" (first occurrence) → [header_block, body]
6. Split header_block on "\n" → [command, header1, header2, ...]
7. For each header line, split on first ":" → key, value
8. Return {command, headers, body}
```

### Edge Cases

| Input | Result |
| - | - |
| `\n` | Heartbeat (null) |
| `\n\n\n` | Heartbeat (null) |
| `\x00` | Heartbeat (null) |
| Frame with no body | Body is empty string |
| Header value containing `:` | Split only on *first* colon |

## Complete Frame Exchange

Here is the full frame sequence for a typical session:

```text theme={null}
Client                                Server
  │                                      │
  │  CONNECT                             │
  │  accept-version:1.2                  │
  │  heart-beat:10000,10000              │
  │  \x00                               │
  ├─────────────────────────────────────►│
  │                                      │
  │                          CONNECTED   │
  │                          version:1.2 │
  │              heart-beat:10000,10000 │
  │                                \x00  │
  │◄─────────────────────────────────────┤
  │                                      │
  │  SUBSCRIBE                           │
  │  id:sub-0                            │
  │  destination:/topic/change/{org}     │
  │  \x00                               │
  ├─────────────────────────────────────►│
  │                                      │
  │  \n  (heartbeat)                     │
  ├─────────────────────────────────────►│
  │                                      │
  │                     \n  (heartbeat)  │
  │◄─────────────────────────────────────┤
  │                                      │
  │                            MESSAGE   │
  │            destination:/topic/...    │
  │                                      │
  │                  {"entity":"..."}    │
  │                                \x00  │
  │◄─────────────────────────────────────┤
  │                                      │
  │  \n  (heartbeat)                     │
  ├─────────────────────────────────────►│
  │                                      │
  │  DISCONNECT                          │
  │  \x00                               │
  ├─────────────────────────────────────►│
  │                                      │
  │           [WebSocket close]          │
  │◄─────────────────────────────────────┤
```

## Differences from Full STOMP 1.2

The Rhombus implementation uses a subset of STOMP 1.2. Notable differences:

| Feature | STOMP 1.2 Spec | Rhombus Implementation |
| - | - | - |
| `SEND` command | Supported | Not used (server-push only) |
| `UNSUBSCRIBE` | Supported | Not needed (single topic) |
| `ACK`/`NACK` | Supported | Not used (auto-acknowledge) |
| `RECEIPT` | Supported | Not used |
| `ERROR` frame | Supported | May be sent on server errors |
| `content-length` header | Optional | Not required |
| Transaction support | Supported | Not used |

This means you do **not** need a full STOMP client library. The protocol subset is simple enough to implement manually, as shown in the [Code Examples](/websocket/code-examples).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.