mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-20 10:01:00 +00:00
* docs(wiki): add new Quickstart to help with using Sync There is a slew of notes that try to explain or show this so a Quickstart can help bring everything into one place. * docs(wiki): combine "First Steps" into single note with relevant links * docs(wiki): update index notes * docs(wiki): fix remaining broken external links * docs(wiki): add core developer How-To guides to orient first-time devs The majority of the documentation is currently spread across several files ins "docs/" and READMEs. Over time these can be consolidated into the wiki while retaining the common CONTRIBUTING.md as a valid entry point. * docs(wiki): add basic guides for plugins and issue integration As with the core development docs, there is too much to add here right now. These notes will serve as a simple entry to other resources. * docs(wiki): add basic reference note for theming * docs(wiki): add basic Translation guide * docs(wiki): rename Theming and linting to clean up headings * docs(wiki): add heading lint exception for GH-specific nav pages; rework sidebar and index pages Sidebar should be a quick-access for the more common topics grouped thematically with the X.00 notes simply enumerating all the notes where appropriate.
217 lines
11 KiB
Markdown
Executable file
217 lines
11 KiB
Markdown
Executable file
# APIs
|
||
|
||
This reference is the entrypoint for working with Super Productivity's APIs. The app 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. SuperSync is very new and is still in beta. 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 50 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/`.
|