WebSocket /stream/ingest
Wire-level reference for device-side streaming.
The endpoint devices use to push raw sensor samples.
wss://api.raeh.io/stream/ingestQuery parameters
| Name | Required | Description |
|---|---|---|
api_key | ✓ | Your raeh_* API key. |
device_id | ✓ | Opaque per-unit string (MAC, serial, UUID). Stable per physical device. |
device_model_id | ✓ | UUID of a device model registered under your account. |
Key can also be supplied via Authorization: Bearer <key> subprotocol if your runtime supports it. Query parameter is the pragmatic default.
Handshake
Immediately after the WebSocket opens, the server sends one JSON text message describing the session and the slot assignments for this device's modality channels:
{
"session_id": "ad225407-36de-48b1-bcf2-14d5c057aeca",
"slots": [
{
"slot_id": 0,
"modality_channel_id": "9f3a...",
"modality": "ppg_green",
"sample_rate_hz": 100,
"bit_depth": 16,
"num_channels": 1
}
]
}Your firmware should parse this, map each modality to its slot_id, and use those IDs in frame headers.
Subsequent messages
After the handshake, all messages (both directions) are binary frames using the layout on Binary frame format.
The server does not send anything during normal streaming. If the server needs to close the session, it sends a WebSocket close frame with a numeric code and text reason.
Close codes
| Code | Reason | When |
|---|---|---|
| 1000 | Normal closure | Either side cleanly closed. |
| 4001 | Authentication failed | api_key missing, invalid, revoked, or bound to a different account. |
| 4004 | Resource not found / bad config | device_model_id doesn't exist, has no modality channels, or a frame's slot_id isn't in the manifest. |
The close-frame reason is a human-readable string. Log it verbatim when debugging.
One device, one session
A single (device_model_id, device_id) can only have one active session at a time. If a new connection arrives with the same pair, the previous session is closed and the new one takes its place.
This makes reconnection safe: just reconnect, the old session auto-cleans.
Pacing
There's no explicit rate limit, but:
- The pipeline emits insights based on real-time windows. Bursting data faster than real-time won't make insights arrive sooner.
- Excessive sustained bandwidth may be rate-limited in future. Target 1 frame / second at your sensor's natural buffering interval.
Idle behavior
If no frames arrive for an extended period the session is still considered active; Raeh doesn't currently auto-close idle ingest connections. That said, don't rely on that: hold the connection open only when your device has data to send.
Frame validation errors
Frames that violate the format (wrong slot_id, payload size mismatch, header too short) cause the server to close with code 4004 and a reason like:
payload size mismatch for slot 0 (ppg_green): got 180 bytes, expected 200After a format error, reconnecting without fixing the encoding will fail the same way.