Sync Protocol Reference
Complete type reference for the Periscope WebSocket and REST sync protocol
The sync protocol defines the message format for communication between the Periscope browser extension and the Periscope service. Messages are exchanged over WebSocket for real-time sync or via the REST API for batch operations.
SyncMessage
The top-level envelope for all sync operations.
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique message identifier (UUID v4) |
type | SyncOperationType | Yes | The operation being performed |
timestamp | string | Yes | ISO 8601 timestamp of when the message was created |
userId | string | Yes | Authenticated user ID |
extensionId | string | Yes | Unique identifier of the browser extension instance |
payload | SyncPayload | Yes | Operation-specific payload (discriminated on type) |
Example
{
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"type": "navigate",
"timestamp": "2026-03-02T14:30:00.000Z",
"userId": "usr_abc123",
"extensionId": "ext_def456",
"payload": {
"type": "navigation",
"tabId": "tab_789",
"url": "https://docs.uselovelace.com/periscope",
"previousUrl": "https://docs.uselovelace.com",
"title": "Periscope - Lovelace Developer Portal",
"transitionType": "link",
"navigationTime": 320
}
}
SyncOperationType
Enum of valid operation types for SyncMessage.type.
| Value | Description |
|---|---|
create | Create a new browser context record |
update | Update an existing browser context |
delete | Delete a browser context |
activate | Mark a tab as the active tab |
deactivate | Mark a tab as inactive |
navigate | Record a page navigation event |
heartbeat | Keep-alive signal with extension status |
SyncPayload Variants
The payload field is a discriminated union. The type field determines which variant applies.
ContextSyncPayload
Used with create, update, and delete operations.
| Field | Type | Required | Description |
|---|---|---|---|
type | "context" | Yes | Discriminator |
operation | "create" | "update" | "delete" | Yes | The context operation |
context | BrowserContext | Yes | The full browser context object |
delta | object | No | Partial update fields (for update operations only) |
TabActivationPayload
Used with activate and deactivate operations.
| Field | Type | Required | Description |
|---|---|---|---|
type | "tab_activation" | Yes | Discriminator |
tabId | string | Yes | ID of the tab being activated or deactivated |
previousTabId | string | No | ID of the previously active tab |
windowId | string | No | Browser window ID |
url | string | No | URL of the activated tab |
title | string | No | Title of the activated tab |
NavigationPayload
Used with navigate operations.
| Field | Type | Required | Description |
|---|---|---|---|
type | "navigation" | Yes | Discriminator |
tabId | string | Yes | ID of the tab where navigation occurred |
url | string | Yes | Destination URL |
previousUrl | string | No | URL before navigation |
title | string | No | Page title of the destination |
transitionType | enum | Yes | How the navigation was triggered |
navigationTime | number | No | Navigation duration in milliseconds |
transitionType values: link, typed, auto_bookmark, auto_subframe, manual_subframe, generated, start_page, form_submit, reload, keyword, keyword_generated
HeartbeatPayload
Used with heartbeat operations. Must be sent at least every 60 seconds (recommended: 25-30 seconds).
| Field | Type | Required | Description |
|---|---|---|---|
type | "heartbeat" | Yes | Discriminator |
activeTabId | string | No | Currently active tab ID |
totalTabs | number | No | Total number of open tabs |
extensionVersion | string | No | Installed extension version |
browserInfo | string | No | Browser name and version |
SyncResponse
Returned by the server for every SyncMessage.
| Field | Type | Required | Description |
|---|---|---|---|
messageId | string | Yes | ID of the original SyncMessage this responds to |
success | boolean | Yes | Whether the operation succeeded |
timestamp | string | Yes | ISO 8601 server timestamp |
result | SyncResult | No | Operation-specific result (present on success) |
error | SyncError | No | Error details (present on failure) |
Example
{
"messageId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"success": true,
"timestamp": "2026-03-02T14:30:00.050Z",
"result": {
"type": "navigation",
"contextId": "ctx_xyz789",
"processed": true
}
}
SyncResult Variants
The result field is a discriminated union on type.
ContextSyncResult
| Field | Type | Description |
|---|---|---|
type | "context" | Discriminator |
contextId | string | Server-assigned context ID |
version | number | Context version after the operation |
TabActivationResult
| Field | Type | Description |
|---|---|---|
type | "tab_activation" | Discriminator |
acknowledged | boolean | Whether the activation was recorded |
NavigationResult
| Field | Type | Description |
|---|---|---|
type | "navigation" | Discriminator |
contextId | string | Context ID for the new page |
processed | boolean | Whether the navigation was fully processed |
HeartbeatResult
| Field | Type | Description |
|---|---|---|
type | "heartbeat" | Discriminator |
serverTime | string | Current server time (for clock sync) |
configUpdate | SyncConfiguration | Updated configuration, if changed server-side |
SyncError
Returned when a sync operation fails.
| Field | Type | Required | Description |
|---|---|---|---|
type | SyncErrorType | Yes | Error category |
message | string | Yes | Human-readable error description |
code | string | Yes | Machine-readable error code |
details | object | No | Additional error context |
retryAfter | number | No | Seconds to wait before retrying (for rate limit errors) |
SyncErrorType
| Value | Description |
|---|---|
authentication_error | Invalid or expired authentication token |
authorization_error | User lacks permission for this operation |
validation_error | Payload failed schema validation |
not_found | Referenced resource does not exist |
conflict | Operation conflicts with current state (e.g. stale version) |
rate_limit | Too many requests; check retryAfter |
server_error | Internal server error |
connection_error | WebSocket connection issue |
BatchSyncMessage
Send multiple sync operations in a single request via the REST API.
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique batch identifier (UUID v4) |
userId | string | Yes | Authenticated user ID |
extensionId | string | Yes | Extension instance identifier |
timestamp | string | Yes | ISO 8601 timestamp |
messages | SyncMessage[] | Yes | Array of individual sync messages |
BatchSyncResponse
Response to a BatchSyncMessage.
| Field | Type | Required | Description |
|---|---|---|---|
messageId | string | Yes | ID of the original BatchSyncMessage |
timestamp | string | Yes | ISO 8601 server timestamp |
results | SyncResponse[] | Yes | Individual results for each message (in order) |
partialSuccess | boolean | Yes | true if some messages succeeded and others failed |
When partialSuccess is true, the HTTP status code is 207 Multi-Status. Check individual results entries for per-message success/failure.
SyncConfiguration
Server-provided configuration for the extension sync behavior. Returned in heartbeat responses when configuration changes.
| Field | Type | Default | Description |
|---|---|---|---|
heartbeatInterval | number | 30000 | Milliseconds between heartbeat messages |
batchSize | number | 50 | Maximum messages per batch request |
batchTimeout | number | 5000 | Milliseconds to wait before flushing a partial batch |
retryAttempts | number | 3 | Maximum retry attempts for failed operations |
retryDelay | number | 1000 | Base delay in milliseconds for retry backoff |
enabledContextTypes | string[] | ["*"] | Which context types to sync (e.g. ["text.selection", "page.navigation"]) |
privacySettings | object | {} | Privacy filter overrides from the server |
ConnectionState
Enum representing the WebSocket connection lifecycle.
| Value | Description |
|---|---|
disconnected | No active connection |
connecting | Connection attempt in progress |
connected | Connection established and authenticated |
reconnecting | Attempting to re-establish a dropped connection |
error | Connection failed; see ConnectionStatus.errorMessage |
ConnectionStatus
Full status of the WebSocket connection.
| Field | Type | Description |
|---|---|---|
state | ConnectionState | Current connection state |
lastConnected | string | ISO 8601 timestamp of last successful connection |
lastHeartbeat | string | ISO 8601 timestamp of last heartbeat sent |
errorMessage | string | Error description if state is error |
retryCount | number | Number of consecutive reconnection attempts |
queuedMessages | number | Messages queued while disconnected |
Queued messages are automatically sent in order when the connection is re-established. If the queue exceeds 1000 messages, the oldest messages are dropped.