LiteTextShare

LiteTextShare API Docs

LiteTextShare (by Lite Lake / ่ฝปๆน–) pickup-code mode API reference. This page is for humans; AI agents should fetch the raw Markdown linked below.

๐Ÿค– AI agents / crawlers: fetch the raw Markdown directly:/docs/api.md(English)/docs/api.zhs.md(Chinese)

TextShare API (LiteTextShare Backend)

Text express-cabinet (TextShare) backend API โ€” the single source of truth for frontend (BFF) and AI agent integration. Any change to this document MUST land in the same release as the corresponding API change.

  • Base URL (REST, via BFF proxy): https://textshare.litelake.com/api/**
  • Collaborative editing (WebSocket, direct connection, NOT via BFF): wss://ws.textshare.{env}/collab/{noteId}?token={editToken} โ€” the wsUrl base is returned by the create/verify responses, clients never assemble it.

Conventions

  • All REST endpoints are POST + application/json (except /docs/* and the WebSocket endpoint, which are GET).
  • Unified response envelope: { "code": number, "message": string, "data": T }. Success: code = 200.
  • Business errors use HTTP 200 and are distinguished by body.code (4101/4103/4104). Rate limiting uses real HTTP 429 + Retry-After; storage outage (fail-closed) uses real HTTP 503.
  • All requests SHOULD carry the X-Device-Id header (UUID from localStorage). Invalid/missing values degrade brute-force protection to IP-only dimension (no error).

POST /api/public/notes โ€” create note and issue pickup code

Create a note with locally-written initial content (write first, generate code afterwards). The note is immediately active.

Request body:

{
  "mode": "md",
  "initState": "<base64(V1 update of the local Y.Doc)>"
}
  • mode: txt | md (whitelist; anything else โ†’ 4103)
  • initState: base64 of the local Y.Doc's Y.encodeStateAsUpdate() (V1). An empty string means an empty document. The server applies the update to an empty doc, folds it, and measures the plain-text byte length.

Response data:

{
  "noteId": "cz9fkq2wm4xv...",
  "pickupCode": "K7M2XQ",
  "mode": "md",
  "expiresAt": "2026-09-16T08:00:00Z",
  "wsUrl": "wss://ws.textshare.{env}/collab",
  "editToken": "9f2c8e...64 hex chars"
}

Errors: 4103 invalid mode / initState not applicable (HTTP 200), 4104 text exceeds 128 KB (HTTP 200), 429 rate limited (12/hour + 30/day per IP, real HTTP 429 + Retry-After), 503 storage unavailable (fail-closed).

POST /api/public/pickup/verify โ€” exchange pickup code for collaboration entry

Request body:

{ "pickupCode": "K7M2XQ" }

The code is normalized server-side: strip spaces/hyphens, uppercase, Oโ†’0, I/Lโ†’1. Response data has the same shape as the create response (pickupCode echoes the normalized value).

Errors: 4101 pickup code invalid or expired โ€” unified message to prevent enumeration (HTTP 200; each failure increments per-IP and per-device counters). Brute-force protection: 5 failures / 10 minutes on EITHER dimension blocks the caller with real HTTP 429 + Retry-After. Counters are not reset by success. Redis outage โ†’ real HTTP 503 (fail-closed).

GET /collab/{noteId}?token={editToken} โ€” collaboration WebSocket

Yjs collaboration endpoint served by a Hocuspocus-protocol-compatible server (@hocuspocus/provider interop; every frame carries the VarString(docName) prefix). Direct browser connection (never via BFF; gateway forwards per-host).

Handshake authorization (performed before the WebSocket upgrade):

  1. noteId exists, status = active, not expired (Redis-cached 60 s + MySQL fallback; expired/not-found โ†’ rejected with 401, business code 4102)
  2. editToken is valid and bound to this noteId (Redis; miss or Redis failure โ†’ rejected, fail-closed, business code 4105)
  3. Per-IP connection count < 10, peers per room < 16, single update <= 768 KB, single frame <= 1 MB

After the upgrade the server runs the y-protocols sync handshake (SyncStep1/2), broadcasts awareness (cursors/presence), and persists every commit as an incremental V1 update (append-then-compact into MySQL: notes.snapshot + note_updates log). Documents expire 48 h after creation; expiry closes rooms forcefully (clients receive a close event).

There are no read-only connections: possessing the token grants edit rights (v1 product definition).

GET /docs/api.md, /docs/api.en.md, /docs/api.zhs.md

This document (embedded in the binary; en is the default/fallback, zhs is Simplified Chinese). Served as text/markdown with Cache-Control: no-cache.

GET /api/health, /api/ready

Framework built-in liveness/readiness probes (gateway healthcheck target).

Error code table

body.codeMeaningHTTP status
200success200
400invalid arguments (binding)200
4101PICKUP_NOT_VALID (unified anti-enumeration message)200
4102NOTE_NOT_FOUND / expired (WS Authorize; REST does not reach it)200
4103INVALID_ARGUMENT (mode / initState)200
4104NOTE_TOO_LARGE (> 128 KB plain text after fold)200
4105EDIT_TOKEN_INVALID (WS handshake rejected)200
429RATE_LIMITED429 + Retry-After
503STORAGE_UNAVAILABLE (Redis outage, fail-closed)503
500internal error500

Note: the baseline rate-limit middleware on /api/public write methods (30/min/IP) responds with its own body shape when triggered; clients must treat 429 by HTTP status code, not by body shape.