mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-23 16:07:27 +00:00
Includes backward compatibility: client accepts both CONFLICT_SUPERSEDED and CONFLICT_STALE from the server, and the server keeps a deprecated CONFLICT_STALE alias. Remove after all deployments are updated.
217 lines
11 KiB
Markdown
Executable file
217 lines
11 KiB
Markdown
Executable file
# APIs
|
||
|
||
Super Productivity exposes **two API systems**: the **Sync Server REST API** (for data synchronization) and the **Plugin API** (for extending the app). This reference summarizes both; full request/response schemas and examples live in the repository (Sync Server: `packages/super-sync-server/`; Plugin API: `packages/plugin-api/` and `docs/plugin-development.md`).
|
||
|
||
## 1. Sync Server REST API
|
||
|
||
The Sync Server is a custom, operation-based synchronization service (event-sourcing style). It is **not** WebDAV. It is intended for use with the built-in SuperSync sync provider. See [[2.08-Choose-Sync-Backend]] and [[2.09-Configure-Sync-Backend]] for user-facing sync options.
|
||
|
||
### Authentication and Authorization
|
||
|
||
All sync endpoints require **JWT Bearer** authentication: `Authorization: Bearer <token>`.
|
||
|
||
- **Token expiry:** 7 days.
|
||
- **Environment:** Server requires `JWT_SECRET` (minimum 32 characters).
|
||
- **Token contents:** `userId`, `email`, `tokenVersion` (for invalidation).
|
||
- Invalid or missing token returns 401.
|
||
|
||
### Authentication Endpoints
|
||
|
||
**Traditional:**
|
||
|
||
- `POST /api/register` — User registration (email verification required).
|
||
- `POST /api/login` — Password login.
|
||
- `POST /api/verify-email` — Email verification.
|
||
- `POST /api/replace-token` — Replace compromised JWT (requires current auth).
|
||
|
||
**Passkey (WebAuthn):**
|
||
|
||
- `POST /api/register/passkey/options` — Registration options.
|
||
- `POST /api/register/passkey/verify` — Verify registration.
|
||
- `POST /api/login/passkey/options` — Authentication options.
|
||
- `POST /api/login/passkey/verify` — Verify authentication.
|
||
- `POST /api/recover/passkey` — Request passkey recovery (e.g. magic link).
|
||
- `POST /api/recover/passkey/options` — Recovery registration options.
|
||
- `POST /api/recover/passkey/complete` — Complete recovery.
|
||
|
||
**Magic link:**
|
||
|
||
- `POST /api/login/magic-link` — Request magic link email.
|
||
- `POST /api/login/magic-link/verify` — Verify magic link token.
|
||
|
||
**Account:**
|
||
|
||
- `DELETE /api/account` — Delete user and all data (requires auth).
|
||
|
||
### Synchronization Endpoints
|
||
|
||
All require authentication.
|
||
|
||
**Operations:**
|
||
|
||
- `POST /api/sync/ops` — Upload operations (incremental). Request: `ops[]`, `clientId`, optional `lastKnownServerSeq`, optional `requestId` (deduplication).
|
||
- `GET /api/sync/ops?sinceSeq={seq}&limit={limit}&excludeClient={clientId}` — Download operations. Query: `sinceSeq` (required), `limit` (default 500, max 1000), `excludeClient` (optional).
|
||
|
||
**Snapshots:**
|
||
|
||
- `GET /api/sync/snapshot` — Get full state snapshot.
|
||
- `POST /api/sync/snapshot` — Upload full state (backup/repair/migration). Body limit 30 MB (compressed).
|
||
|
||
**Status and maintenance:**
|
||
|
||
- `GET /api/sync/status` — Sync status and storage info.
|
||
- `DELETE /api/sync/data` — Delete all sync data for the user (e.g. encryption password change).
|
||
- `GET /api/sync/restore-points?limit={limit}` — List restore points (limit 1–100).
|
||
- `GET /api/sync/restore/{serverSeq}` — Get state snapshot at a specific sequence.
|
||
|
||
**Health:**
|
||
|
||
- `GET /health` — Database connectivity check (no auth). Returns 200 with `{ status: 'ok', db: 'connected' }` or 503 on failure.
|
||
|
||
### Request/Response Overview
|
||
|
||
- **Upload ops:** Body is an array of operations; each has `id`, `clientId`, `actionType`, `opType`, `entityType`, `entityId`/`entityIds`, `payload`, `vectorClock`, `timestamp`, `schemaVersion`, optional `isPayloadEncrypted`. Response: `results[]` (per-op accepted/rejected + `serverSeq`), optional `newOps`, `latestSeq`, optional `hasMorePiggyback`, optional `deduplicated`.
|
||
- **Download ops:** Response: `ops`, `hasMore`, `latestSeq`, optional `gapDetected`, optional `latestSnapshotSeq`, optional `snapshotVectorClock`, `serverTime`.
|
||
- **Snapshot:** Response: `state`, `serverSeq`, `generatedAt`. Upload snapshot body: `state`, `clientId`, `reason`, `vectorClock`, `schemaVersion`, optional `isPayloadEncrypted`.
|
||
- **Status:** Response: `latestSeq`, `devicesOnline`, optional `snapshotAge`, `storageUsedBytes`, `storageQuotaBytes`.
|
||
|
||
Exact schemas (Zod on server, TypeScript types in repo) are in `packages/super-sync-server/src/sync/sync.types.ts` and `sync.routes.ts`.
|
||
|
||
### Error Codes
|
||
|
||
Structured error codes (for client handling) include: `VALIDATION_FAILED`, `INVALID_OP_ID`, `INVALID_OP_TYPE`, `INVALID_ENTITY_TYPE`, `INVALID_ENTITY_ID`, `INVALID_PAYLOAD`, `PAYLOAD_TOO_LARGE`, `INVALID_VECTOR_CLOCK`, `INVALID_CLIENT_ID`, `CONFLICT_CONCURRENT`, `CONFLICT_SUPERSEDED`, `DUPLICATE_OPERATION`, `RATE_LIMITED`, `STORAGE_QUOTA_EXCEEDED`, `ENCRYPTED_OPS_NOT_SUPPORTED`, `SYNC_IMPORT_EXISTS`, `INTERNAL_ERROR`. Defined in `sync.types.ts` (`SYNC_ERROR_CODES`).
|
||
|
||
### Rate Limits (per endpoint)
|
||
|
||
- Email verification: 20 / 15 min.
|
||
- Token replacement: 5 / 15 min.
|
||
- Account deletion: 3 / 15 min.
|
||
- Passkey registration: 10 / 15 min.
|
||
- Passkey login: 20 / 15 min.
|
||
- Passkey recovery (request/options/complete): 5–10 / 15 min.
|
||
- Magic link request: 5 / 15 min; verify: 10 / 15 min.
|
||
- Upload ops: 100 / 1 min.
|
||
- Download ops: 200 / 1 min.
|
||
- Snapshot (GET): 10 / 5 min.
|
||
|
||
### Storage Quotas (Sync Server)
|
||
|
||
- **Per user:** Default 100 MB. Enforced before accepting uploads; automatic cleanup (restore points and old operations) when over quota.
|
||
- **Upload limits:** Max payload 20 MB; max operations per upload 100. Compressed ops body: 10 MB; compressed snapshot: 30 MB; decompressed cap (zip-bomb protection): 100 MB.
|
||
|
||
### Compression
|
||
|
||
- **Request:** Gzip via `Content-Encoding: gzip`. Android can send base64-encoded gzip with `Content-Transfer-Encoding: base64`.
|
||
- **Response:** Server may send compressed responses where configured.
|
||
|
||
### CORS
|
||
|
||
Configurable via environment/config. Typical allowed headers include `Authorization`, `Content-Type`, `Content-Encoding`, `X-Expected-Rev`, `X-Force-Overwrite`, `X-Requested-With`. Credentials supported.
|
||
|
||
### Data Retention
|
||
|
||
Operations, devices, and related validation data are retained for **45 days**. Older data is purged.
|
||
|
||
### Request Deduplication
|
||
|
||
Upload ops accepts optional `requestId`. Repeated requests with the same `requestId` receive cached results (and fresh piggybacked ops if applicable), so clients can retry safely without duplicating operations.
|
||
|
||
### End-to-End Encryption
|
||
|
||
Payloads can be encrypted client-side; server stores them as opaque blobs. Restore-at-sequence is not supported when operations are encrypted (`ENCRYPTED_OPS_NOT_SUPPORTED`).
|
||
|
||
---
|
||
|
||
## 2. Plugin API
|
||
|
||
The Plugin API is exposed to plugins via a global `PluginAPI` object. Plugins run in a sandboxed environment (VM or iframe). See [[3.05-Web-App-vs-Desktop]] for web limitations (e.g. Node-only plugins disabled, iframe API restrictions). Full types and the development guide: `packages/plugin-api/src/types.ts`, `docs/plugin-development.md`.
|
||
|
||
### Plugin API Categories
|
||
|
||
**Data — Tasks:**
|
||
|
||
- `getTasks()`, `getArchivedTasks()`, `getCurrentContextTasks()` — Read tasks.
|
||
- `addTask(taskData)`, `updateTask(taskId, updates)`, `deleteTask(taskId)` — Create/update/delete.
|
||
- `batchUpdateForProject(request)` — Batch create/update/delete/reorder for a project.
|
||
- `reorderTasks(taskIds, contextId, contextType)` — Reorder tasks.
|
||
|
||
**Data — Projects:**
|
||
|
||
- `getAllProjects()`, `addProject(projectData)`, `updateProject(projectId, updates)`.
|
||
|
||
**Data — Tags:**
|
||
|
||
- `getAllTags()`, `addTag(tagData)`, `updateTag(tagId, updates)`.
|
||
|
||
**Data — Simple counters:**
|
||
|
||
- `setCounter(id, value)`, `getCounter(id)`, `incrementCounter(id, incrementBy)`, `decrementCounter(id, decrementBy)`, `deleteCounter(id)`, `getAllCounters()`.
|
||
|
||
**UI:**
|
||
|
||
- `showSnack(snackCfg)`, `notify(notifyCfg)` — Notifications.
|
||
- `openDialog(dialogCfg)`, `showIndexHtmlAsView()` — Dialogs and plugin UI.
|
||
|
||
**Registration (main plugin context only; not in iframe):**
|
||
|
||
- `registerHeaderButton(config)`, `registerMenuEntry(config)`, `registerShortcut(config)`, `registerSidePanelButton(config)`, `registerHook(hook, handler)`.
|
||
|
||
**Persistence:**
|
||
|
||
- `persistDataSynced(dataStr)`, `loadSyncedData()`, `getConfig()` — Plugin-specific storage and config.
|
||
|
||
**Advanced:**
|
||
|
||
- `executeNodeScript(request)` — Run Node.js scripts (Electron only, `nodeExecution` permission and user consent).
|
||
- `dispatchAction(action)` — Dispatch NgRx actions (allowed subset).
|
||
- `downloadFile(filename, data)`, `isWindowFocused()`, `onWindowFocusChange(handler)`.
|
||
|
||
### Hooks (Events)
|
||
|
||
Plugins can register handlers for: `taskCreated`, `taskComplete`, `taskUpdate`, `taskDelete`, `currentTaskChange`, `finishDay`, `languageChange`, `persistedDataUpdate`, `action`, `anyTaskUpdate`, `projectListUpdate`. Payload types are defined in `plugin-api` types (`HookPayloadMap`).
|
||
|
||
### Plugin Data Types
|
||
|
||
Core types (Task, Project, Tag, ProjectFolder, etc.) and batch types (`BatchUpdateRequest`, `BatchUpdateResult`, `BatchOperation`, etc.) are in `packages/plugin-api/src/types.ts`.
|
||
|
||
### Plugin Manifest
|
||
|
||
Plugins require `manifest.json`: `name`, `id`, `manifestVersion`, `version`, `minSupVersion`, optional `description`, `hooks`, `permissions`, optional `iFrame`, `isSkipMenuEntry`, `type`, `assets`, `icon`, `nodeScriptConfig`, `sidePanel`, `jsonSchemaCfg`. See `PluginManifest` in the repo.
|
||
|
||
### Plugin Permissions
|
||
|
||
- **nodeExecution:** Required for `executeNodeScript()` (Electron only; user consent). See [[3.05-Web-App-vs-Desktop]] and [[3.06-User-Data]] for file-system and desktop-only behavior.
|
||
- Other permissions may gate specific API methods; see the plugin development guide.
|
||
|
||
### Iframe Restrictions
|
||
|
||
When a plugin uses an iframe UI, the following are **not** available: `registerHeaderButton`, `registerMenuEntry`, `registerSidePanelButton`, `registerShortcut`, `registerHook`, `execNodeScript`. Iframe content is subject to CSP (e.g. no external scripts; same-origin or inlined only).
|
||
|
||
---
|
||
|
||
## 3. Versioning and Compatibility
|
||
|
||
### Schema Versioning (Sync)
|
||
|
||
- **Current schema version:** 1 (shared schema in `packages/shared-schema`).
|
||
- **Minimum supported:** 1.
|
||
- **Max version skip:** 3 (if remote data is more than 3 versions ahead, client should update).
|
||
- Operations and snapshots carry `schemaVersion`; server validates and may reject unsupported versions.
|
||
|
||
### Vector Clocks
|
||
|
||
Sync uses vector clocks for conflict resolution. Server validates/sanitizes clocks: max 100 entries; keys max 255 chars; values 0–10,000,000. Invalid entries are stripped.
|
||
|
||
### API Validation (Sync Server)
|
||
|
||
- Operation IDs: 1–255 characters. Client IDs: alphanumeric, underscore, hyphen; max 255.
|
||
- Entity types: 1–255 characters. Schema version: 1–100.
|
||
- Payload validation by op type (CRT, UPD, DEL, MOV, BATCH, SYNC_IMPORT, etc.); see `validatePayload` in `sync.types.ts`.
|
||
|
||
---
|
||
|
||
## Notes
|
||
|
||
- **Sync Server:** Production-oriented (JWT, rate limiting, CORS, Helmet). Multi-instance deployment has limitations (e.g. passkey challenge storage in memory; snapshot generation locks); single-instance is the typical deployment.
|
||
- **Plugin API:** Sandboxed; iframe and Electron have different capabilities. See [[3.05-Web-App-vs-Desktop]] and the repo plugin guide.
|
||
- **Further documentation:** Sync Server README and auth docs in `packages/super-sync-server/`; Plugin API and examples in `packages/plugin-api/`, `docs/plugin-development.md`, and example plugins under `packages/plugin-dev/`.
|