Aoba LiveStore Sync WebSocket API 1.0.0
  • Proprietary

LiveStore event synchronization WebSocket API for cross-device data sync.

Overview

The LiveStore sync WebSocket enables real-time event synchronization between a user's devices using an event-sourced architecture. This channel operates as a peer-to-peer relay where the server routes messages between devices without persisting events.

Architecture

Device A ──┐                    ┌── Device B
           │   ┌──────────┐     │
           ├──>│  Server  │<────┤
           │   │ (Relay)  │     │
           │   └──────────┘     │
Device C ──┘                    └── Device D
  • Event-Sourced: All state changes are events in an append-only log
  • Local-First: Each device maintains its own SQLite database
  • Peer-to-Peer Sync: Devices sync history directly through server relay
  • No Server Persistence: Server only routes messages, doesn't store events

Connection

  • Endpoint: /api/v1/livestore/sync
  • Protocol: WebSocket (RFC 6455)
  • Authentication: JWT token via auth_token cookie or ?token= query parameter

Connection Examples

Same-origin (cookie-based):

const ws = new WebSocket('wss://api.example.com/api/v1/livestore/sync');

Cross-origin (token parameter):

const ws = new WebSocket(`wss://api.example.com/api/v1/livestore/sync?token=${jwtToken}`);

Message Flow

Real-time Sync (Push)

Device A              Server              Device B
   │                    │                    │
   │──── push ─────────>│                    │
   │                    │──── push ─────────>│
   │<─── ack ───────────│                    │
   │                    │                    │

History Sync (Peer Pull)

New Device            Server            Existing Device
   │                    │                    │
   │── peer_pull ──────>│                    │
   │                    │── peer_pull ──────>│
   │                    │<─ peer_pull_resp ──│
   │<─ peer_pull_resp ──│                    │
   │                    │                    │

Protocol Reference

This implementation follows the @livestore/adapter-web protocol specification with custom extensions for peer-to-peer history sync.

Client Identification

Each client must identify itself on first message:

  • clientId: Unique device identifier (persisted per device)
  • sessionId: Current session identifier (changes on reconnect)

Servers

  • wss://api.example.com/wssproduction

    Production LiveStore sync server

    Security:
    • HTTP API key
      • Name: auth_token
      • In: cookie

      JWT token stored in HTTP-only cookie named auth_token.

      For cross-origin WebSocket connections, the token can also be passed as a ?token= query parameter.

  • ws://localhost:8080/wsdevelopment

    Development LiveStore sync server

    Security:
    • HTTP API key
      • Name: auth_token
      • In: cookie

      JWT token stored in HTTP-only cookie named auth_token.

      For cross-origin WebSocket connections, the token can also be passed as a ?token= query parameter.

Operations

  • SEND /api/v1/livestore/sync

    Bidirectional WebSocket channel for LiveStore event synchronization.

    This channel supports both sending and receiving messages for full peer-to-peer event synchronization.

    Send sync messages to the server for relay

    Send events or sync requests to the server.

    Message Types

    Type Direction Description
    push Client -> Server -> Peers Push new events to other devices
    pull Client -> Server Request events from server (returns empty + peer list)
    peer_pull Client -> Server -> Peers Request history from online peers
    peer_pull_response Client -> Server -> Requester Respond to peer pull with history

    Push Example

    ws.send(JSON.stringify({
      type: 'push',
      clientId: 'device-abc-123',
      sessionId: 'session-xyz',
      timestamp: Date.now(),
      payload: {
        events: [{
          eventName: 'message.created',
          eventNumber: 42,
          clientId: 'device-abc-123',
          sessionId: 'session-xyz',
          data: { conversationId: '...', text: 'Hello!' },
          timestamp: Date.now()
        }]
      }
    }));
    
    Operation IDsendSyncMessage

    Available only on servers:

    Accepts one of the following messages:

    • #0Push Eventspush

      Push new events to other devices via server relay

      Message IDpush

      Send new events from this device to be relayed to all other online devices of the same user. The server does not persist events.

      allOf

      Examples

    • #1Pull Requestpull

      Request events from server

      Message IDpull

      Request events since a timestamp. Since the server doesn't persist events, this returns an empty list along with a list of online peers that can provide history.

      allOf

      Examples

    • #2Peer Pull RequestpeerPull

      Request history from online peer devices

      Message IDpeerPull

      Request event history directly from other online devices of the same user. The server routes this request to all online peers.

      This enables new devices to sync historical data from existing devices without requiring server-side event storage.

      allOf

      Examples

    • #3Peer Pull ResponsepeerPullResponse

      History response from a peer device

      Message IDpeerPullResponse

      Response to a peer pull request containing historical events from another device. The server routes this back to the requesting device.

      allOf

      Examples

  • RECEIVE /api/v1/livestore/sync

    Bidirectional WebSocket channel for LiveStore event synchronization.

    This channel supports both sending and receiving messages for full peer-to-peer event synchronization.

    Receive sync messages from server

    Receive events and responses relayed from other devices.

    Message Types

    Type Source Description
    push Peer device Events pushed by another device
    pull_response Server Response to pull request (includes online peer list)
    ack Server Acknowledgment of received push
    peer_pull Peer device History request from another device
    peer_pull_response Peer device History response from peer
    error Server Error response

    Message Handling Example

    ws.onmessage = (event) => {
      const msg = JSON.parse(event.data);
    
      switch (msg.type) {
        case 'push':
          // Apply events from peer device
          applyEvents(msg.payload.events);
          break;
    
        case 'ack':
          // Push was acknowledged
          console.log(`${msg.payload.receivedCount} events received`);
          break;
    
        case 'pull_response':
          // Server has no events but provides peer list
          if (msg.onlinePeers?.length > 0) {
            requestHistoryFromPeer(msg.onlinePeers[0]);
          }
          break;
    
        case 'peer_pull':
          // Another device wants history
          respondWithHistory(msg.payload.requestId, msg.payload.sinceTimestamp);
          break;
    
        case 'peer_pull_response':
          // Received history from peer
          applyEvents(msg.payload.events);
          break;
    
        case 'error':
          console.error(`Sync error: ${msg.code} - ${msg.message}`);
          break;
      }
    };
    
    Operation IDreceiveSyncMessage

    Available only on servers:

    Accepts one of the following messages:

    • #0Push Eventspush

      Push new events to other devices via server relay

      Message IDpush

      Send new events from this device to be relayed to all other online devices of the same user. The server does not persist events.

      allOf

      Examples

    • #1Pull ResponsepullResponse

      Response to pull request with events and peer list

      Message IDpullResponse

      Server response to a pull request. Since the server doesn't persist events, this typically contains an empty event list but includes a list of online peers that can provide history via peer_pull.

      allOf

      Examples

    • #2Acknowledgmentack

      Server acknowledgment of received push

      Message IDack

      Sent by the server to acknowledge receipt of a push message. Confirms how many events were received and relayed.

      allOf

      Examples

    • #3Peer Pull RequestpeerPull

      Request history from online peer devices

      Message IDpeerPull

      Request event history directly from other online devices of the same user. The server routes this request to all online peers.

      This enables new devices to sync historical data from existing devices without requiring server-side event storage.

      allOf

      Examples

    • #4Peer Pull ResponsepeerPullResponse

      History response from a peer device

      Message IDpeerPullResponse

      Response to a peer pull request containing historical events from another device. The server routes this back to the requesting device.

      allOf

      Examples

    • #5Error Messageerror

      Error response from server

      Message IDerror

      Sent when the server encounters an error processing a message.

      object

      Error message from server

      Examples

Messages

  • #1Push EventsPush

    Push new events to other devices via server relay

    Message IDPush

    Send new events from this device to be relayed to all other online devices of the same user. The server does not persist events.

    allOf
  • #2Pull RequestPull

    Request events from server

    Message IDPull

    Request events since a timestamp. Since the server doesn't persist events, this returns an empty list along with a list of online peers that can provide history.

    allOf
  • #3Pull ResponsePullResponse

    Response to pull request with events and peer list

    Message IDPullResponse

    Server response to a pull request. Since the server doesn't persist events, this typically contains an empty event list but includes a list of online peers that can provide history via peer_pull.

    allOf
  • #4AcknowledgmentAck

    Server acknowledgment of received push

    Message IDAck

    Sent by the server to acknowledge receipt of a push message. Confirms how many events were received and relayed.

    allOf
  • #5Peer Pull RequestPeerPull

    Request history from online peer devices

    Message IDPeerPull

    Request event history directly from other online devices of the same user. The server routes this request to all online peers.

    This enables new devices to sync historical data from existing devices without requiring server-side event storage.

    allOf
  • #6Peer Pull ResponsePeerPullResponse

    History response from a peer device

    Message IDPeerPullResponse

    Response to a peer pull request containing historical events from another device. The server routes this back to the requesting device.

    allOf
  • #7Error MessageError

    Error response from server

    Message IDError

    Sent when the server encounters an error processing a message.

    object

    Error message from server

Schemas

  • string

    The type of LiveStore sync message

      Allowed values:
    • "push"
    • "pull"
    • "pull_response"
    • "ack"
    • "peer_pull"
    • "peer_pull_response"
  • object

    Base structure for all LiveStore messages

  • object

    A single event in the LiveStore eventlog

  • allOf
  • object

    Payload for push messages

  • allOf
  • object

    Payload for pull requests

  • allOf
  • object

    Payload for pull response messages

  • allOf
  • object

    Payload for acknowledgment messages

  • object

    Error encountered during sync

  • allOf
  • object

    Payload for peer-to-peer pull requests

  • allOf
  • object

    Payload for peer-to-peer pull response

  • object

    Error message from server