Skip to content
MoliSync
Documentation menu
Documentation Protocol

Protocol & data plane

The wire protocol is split into a small HTTP/WebSocket control plane and a streaming data plane. proto/sync.proto mirrors the JSON shapes.

Control plane endpoints

EndpointPurpose
GET /api/v1/recordsList records with kind, limit and before.
POST /api/v1/records/textStore a text record and broadcast it.
POST /api/v1/records/blobStream an image or file body with kind, name, mime and optional X-Blake3.
GET /api/v1/blobs/{id}Download a blob, with HTTP Range support.
GET /api/v1/blobs/{id}/thumbImage preview: server-rendered JPEG, w=64..1024 (default 320), cached on disk.
DELETE /api/v1/records/{id}Delete your own record and blob.
GET /api/v1/relay/{session_id}Relay byte stream using X-Session-Ticket; the connection is hijacked and forwarded both ways.

P2P session

  1. The control plane issues a single-use 32-byte ticket and a candidate pool to both peers.
  2. Both sides complete mutual TLS with their system certificates.
  3. The receiver races LAN and VPN candidates in 300 ms steps.
  4. A direct link streams fixed 49-byte frames.
  5. If nothing answers by 1.2 s, the server relays the same session with io.Copy; the pairing timeout is 15 s.
Note

The relay is transparent byte forwarding. End-to-end protection stays between the two clients, and the server does not write the stream to disk.

Blobs and records

  • POST /api/v1/records/blob streams the body instead of buffering it in memory.
  • GET /api/v1/blobs/{id} supports Range resume on both clients.
  • Text is capped at 64 KiB and stored in SQLite.
  • Delete is owner-only; there is no admin override.

Frames

Data-plane frames are fixed 49 bytes; Android also carries BLAKE3 framing. The relay reuses the same frame stream, so a client cannot tell from the payload whether the bytes arrived directly or through the server.

Reference: proto/sync.proto.