Sync Reference
Change tracking, cursor management, devices, preferences, and conflicts.
Base path: /api/v1/sync/
Change object#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
change_type: created, updated, deleted, moved, renamed.
resource_type: file, folder, share.
Change tracking#
GET /api/v1/sync/changes#
Fetch changes since a cursor.
Query:
| Param | Notes |
|---|---|
cursor |
Opaque cursor from prior response; omit to start from current position |
share_id |
Scope to one share |
limit |
1–5000, default 1000 |
Response:
1 2 3 4 5 6 | |
Required permission: READ on the share.
GET /api/v1/sync/status#
Current cursor position and sync state.
Query: share_id (required), device_id (required).
Response:
1 2 3 4 5 6 | |
Creates a cursor at the current head if none exists.
POST /api/v1/sync/cursor#
Advance the cursor.
Query: share_id, device_id, position.
Response: {cursor_position, last_sync_at}.
POST /api/v1/sync/apply#
Apply client-side changes to the server.
Body:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Resolution values: LAST_WRITER_WINS, KEEP_BOTH, SERVER_WINS, CLIENT_WINS, MANUAL.
Response:
1 2 3 4 5 | |
GET /api/v1/sync/download/{file_id}#
Download file content during sync (range-capable).
Query: version, range_start, range_end.
Headers: Supports Range: bytes=start-end.
Required permission: READ on the file.
Conflicts#
GET /api/v1/sync/conflicts#
List conflicts.
Query:
| Param | Notes |
|---|---|
device_id |
Filter by device |
share_id |
Filter by share |
include_resolved |
Default false |
Response: Array of conflict objects:
1 2 3 4 5 6 7 8 9 10 11 | |
POST /api/v1/sync/conflicts/{conflict_id}/resolve#
Resolve a conflict.
Query: resolution (one of the strategies).
Response: Updated conflict object.
Devices#
GET /api/v1/sync/devices#
List the caller's registered devices.
Response: Array of device objects:
1 2 3 4 5 6 7 8 9 10 | |
POST /api/v1/sync/devices#
Register a device. Returns 201.
Body:
| Field | Notes |
|---|---|
device_id |
Client-generated; opaque string, typically a UUID |
device_name |
Display |
platform |
windows, macos, linux, ios, android, web, cli |
client_version |
Semver string |
PATCH /api/v1/sync/devices/{device_id}#
Update device.
Body: device_name, is_active.
DELETE /api/v1/sync/devices/{device_id}#
Remove device. Returns 204. Cursors associated with the device stop advancing.
POST /api/v1/sync/devices/{device_id}/heartbeat#
Record device activity. Returns 204. Updates last_seen_at.
Sync preferences#
GET /api/v1/sync/devices/{device_id}/preferences#
List per-share sync preferences for a device.
Response:
1 2 3 4 5 6 7 8 9 10 | |
PUT /api/v1/sync/devices/{device_id}/preferences/{share_id}#
Update a single preference.
Body: sync_enabled, selected_folders, excluded_folders.
PUT /api/v1/sync/devices/{device_id}/preferences#
Bulk update.
Body:
1 2 3 4 5 | |
Real-time#
WebSocket /api/v1/sync/ws/{device_id}#
Sync nudges for a device.
Auth: ?token=<JWT> query parameter, or Authorization: Bearer header if the client library supports it.
Server frames: change, sync_preference_updated, force_sync, pong.
Client frames: {"type": "ping"}, {"type": "subscribe"}.
See Real-time WebSocket.
Error codes#
| Code | HTTP | When |
|---|---|---|
SYNC_CONFLICT |
409 | Version mismatch on apply |
SYNC_VERSION_STALE |
409 | base_version_id outdated |
SYNC_CURSOR_INVALID |
400 | Malformed or unknown cursor |
NOT_FOUND |
404 | Device, conflict, or share not found |