The current HTTP and WebSocket protocol is version 2 and is served below /api/v2. Versioned API paths remain stable even though Synclippy v1, the old room-based product, has been retired.
All API responses use Cache-Control: no-store. Health checks are public; archive endpoints require an allowed Tailscale-User-Login when SYNCLIPPY_ALLOWED_LOGINS is configured. Requests carrying a browser Origin must be same-origin or match SYNCLIPPY_ALLOWED_ORIGINS.
| Method | Path | Purpose |
|---|---|---|
GET |
/healthz |
Process health and protocol version |
GET |
/readyz |
Archive database readiness |
| Method | Path | Purpose |
|---|---|---|
POST |
/api/v2/events |
Submit a structured clipboard event |
GET |
/api/v2/events |
List recent events or replay after a sequence |
GET |
/api/v2/events/{eventID} |
Read one event |
DELETE |
/api/v2/events/{eventID} |
Permanently delete one event |
GET |
/api/v2/search?q=... |
Search archived text |
GET |
/api/v2/stream |
Replay and follow events over WebSocket |
GET |
/api/v2/latest |
Download the latest retained representation |
GET |
/api/v2/latest/text |
Return the latest retained text |
GET |
/api/v2/policy |
Read settings and storage usage |
PUT |
/api/v2/policy |
Replace clipboard archive settings |
POST |
/api/v2/admin/reconcile |
Reconcile blob and database state |
List requests accept limit from 1 through 200. after_sequence requests strictly newer events in ascending server-sequence order. Without a replay cursor, recent results are returned newest first.
GET /api/v2/events/{eventID}/representations/{ordinal}
GET /api/v2/events/{eventID}/representations/{ordinal}/preview
The first route downloads the exact retained bytes with the stored media type and sanitized filename. The preview route returns a bounded browser-safe preview when supported. Metadata-only entries have no fabricated download.
The preferred iOS Shortcut request is one standard multipart file:
POST /api/v2/share
Content-Type: multipart/form-data; boundary=...
Content-Disposition: form-data; name="item"; filename="original-name.ext"
Content-Type: <the item's media type>
<exact item bytes>
The multipart body must contain exactly one part. Its field name is ignored; the part filename and bytes are authoritative. Arbitrary safe filenames and extensions are preserved without a file-type table.
In Apple Shortcuts, configure Get Contents of URL as POST and choose a Form request body. Add one File field whose left-hand key is only the plain text item; do not insert a Magic Variable into the key. Put the current Repeat Item in the right-hand value, tap that value token, and set its type to File. Do not add filename or extension query parameters, and do not convert JSON files to a Dictionary.
The legacy raw-body form remains supported:
POST /api/v2/share
Content-Type: <the item's media type>
X-Synclippy-Device-ID: iPhone
X-Synclippy-Filename: optional-name.ext
<raw item bytes>
Raw text may omit the filename. A raw binary body cannot carry its original filename; when none is supplied, Synclippy gives it an explicitly generic .bin name instead of guessing an extension from its MIME type. X-Synclippy-Client-Event-ID is optional and provides idempotency when the caller can persist a stable ID.
Uploads use the same rich-text, media, and file policy as desktop clipboard events. Oversized uploads return 413 and do not create a placeholder row.
- Client events carry
protocolVersion: 2, a stable client event ID, a source device ID, and one or more typed representations. - The server assigns the event ID, accepted timestamp, and monotonically increasing server sequence.
- Repeating the same client event is idempotent; reusing its ID with different content is a conflict.
- Permanent content is centralized in the server archive. Agents retain only synchronization cursors and local operational state.
- The full request and response structures are defined in
backend/internal/protocol.