Sync protocol
Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.
The sync protocol is a simple incremental pull plus a conflict-aware push. The server is the source of truth; the client carries a per-device cursor and reconciles based on UpdatedAt timestamps.
Endpoints
Section titled “Endpoints”| Method | Path | Purpose |
|---|---|---|
GET | /api/sync/pull?since={ISO8601} | Incremental pull of records updated since the given timestamp |
POST | /api/sync/push | Push client changes; receive server-assigned IDs and conflicts |
GET | /api/sync/status | Current sync cursor, last successful sync, queue depth |
GET | /api/sync/events | Audit trail of recent sync activity |
GET | /api/sync/quota | Current usage vs. caps |
All require a JWT. The sync rate-limit policy (30 req/min per user) is applied to push and pull.
The client sends its last-known sync timestamp and receives a SyncPullResponse:
{ "templates": [...], "providers": [...], "sessions": [...], "memories": [...], "todos": [...], "settings": { ... }, "serverTime": "2026-05-03T12:34:56Z"}The client persists serverTime as its new cursor. If since is omitted (first sync), the response contains the full set of records the user owns.
The client batches local changes into a SyncPushRequest and sends them in one shot:
{ "templates": [...], "providers": [...], "sessions": [...], "memories": [...], "todos": [...], "settings": { ... }}The server applies validation (16 unique rules — max field lengths, required fields, format checks), then walks the request:
- Quota check —
QuotaService.CheckQuotaAsyncaborts the entire push with409 quota_exceededif any cap would be violated. - Conflict resolution —
ConflictResolvercompares serverUpdatedAtwith the client-provided value:- Default: last-write-wins (later timestamp wins).
- Server-wins: applied to auth-sensitive data.
- Persist — successful records are written inside a single EF transaction.
The SyncPushResponse contains:
- Server-assigned IDs for new records.
- A
conflictsarray describing per-record decisions (so the client can update its local view). - A new
serverTimecursor.
Validation failures
Section titled “Validation failures”A push that fails validation returns 400 with an errors array; nothing is persisted. The client should surface the errors and retry after the user fixes them.
Cursors
Section titled “Cursors”SyncCursor rows are per-device, not per-user. This lets a single user run multiple devices that move at independent speeds without one device’s late writes pulling another back. The DeviceId is read from the X-Pia-Device-Id header, populated by the desktop client.