MeshDash Docs
R2.0
/
Home API Reference Web Serial API

Web Serial API

API Reference webserial web serial api packet send wakeup session status browser usb ingest
Server-side endpoints that support the browser Web Serial bridge — packet ingestion, send queue, status, sessions, and wakeup frame.

When MESHTASTIC_CONNECTION_TYPE=WEBSERIAL, the server does not open a serial port itself. Instead, the browser holds the port and communicates with the server via these HTTP endpoints. All are mounted at /api/webserial.

These endpoints are used automatically by the browser's WebSerialBridge JavaScript module. You do not need to call them manually. See Web Serial Connection for the user-facing guide.

POST /api/webserial/packet

The browser calls this endpoint to push a decoded packet it read from the serial port into the MeshDash pipeline. The server processes the packet exactly as if it had received it over a native serial connection — it is queued through the packet processing worker, stored in the database, and broadcast over SSE.

The browser sends the raw protobuf bytes; the server decodes them using the Meshtastic Python SDK and runs the full packet processing pipeline (classification, source detection, telemetry extraction, etc.).

POST /api/webserial/packet
Content-Type: application/octet-stream

[raw protobuf bytes]

→ {"status": "ok", "packet_type": "Message"}

POST /api/webserial/send

When POST /api/messages is called while Web Serial mode is active, the window.fetch patch in app.js redirects it to the browser's serial port. However, for messages queued server-side (e.g. by the task scheduler or auto-reply engine), this endpoint provides a queue that the browser polls:

POST /api/webserial/send
Content-Type: application/json

{
  "text": "Hello mesh",
  "destination": "^all",
  "channel": 0
}

→ [encoded bytes ready for serial write, as binary response]

The browser periodically polls this endpoint. If there is a queued outbound message, the server returns the encoded Meshtastic protobuf frame bytes, which the browser writes directly to the serial port.

POST /api/webserial/status

The browser calls this to notify the server of Web Serial connection state changes:

POST /api/webserial/status
Content-Type: application/json

{"status": "connected", "slot_id": "node_0"}

# or
{"status": "disconnected", "slot_id": "node_0"}

On connected, the server marks the Web Serial session as active and begins treating the slot as radio-ready. On disconnected, it clears the ready state so /api/messages returns 503 again until reconnected.

GET /api/webserial/status

Returns the current Web Serial session status for all active slots.

GET /api/webserial/status

{
  "node_0": {
    "connected": true,
    "baud_rate": 115200,
    "rx_bytes": 48291,
    "tx_bytes": 1024,
    "packets_rx": 142,
    "packets_tx": 3,
    "connect_time": 1705329000.0,
    "port_info": {"usbVendorId": 4292, "usbProductId": 60000}
  }
}

GET /api/webserial/sessions

Returns all active Web Serial sessions (one per connected slot). Auth required.

GET /api/webserial/wakeup

Returns the Meshtastic want_config_id protobuf frame as raw bytes. The browser fetches this immediately after opening the serial port and writes the bytes to the port to prompt the radio to send its full node database.

GET /api/webserial/wakeup
→ [binary response: Meshtastic wakeup frame bytes]

Without this handshake, the radio may not send its node database and the dashboard would show no nodes until packets happen to arrive organically.

Packet Framing

The browser reads raw bytes from the serial port and looks for the Meshtastic packet boundary magic bytes:

Magic byte 1: 0x94
Magic byte 2: 0xC3
Followed by: 2-byte big-endian length
Followed by: protobuf payload of that length

The browser accumulates bytes in a buffer until it has a complete framed packet, then POSTs the payload to /api/webserial/packet. Maximum payload size is 512 bytes (_MAX_PAYLOAD).