REST API Reference
The relay's REST surface — the wire spec any client needs to be compatible with a relay (OSS) deployment. Generated straight from the relay's own OpenAPI spec, so it can't drift silently.
REST + WebSocket surface for the DocuShark relay. Source of truth for any
client wanting to be wire-compatible with relay (OSS) deployments.
The relay is a pure OIDC resource server: it validates RS256 bearer
tokens minted by an external issuer and never mints them itself. There
is no password / login surface — user lifecycle lives at the issuer.
All authenticated endpoints expect a bearer token (Authorization: Bearer <jwt>) verified per token-format.md.
Servers
docs
Document CRUD + sharing + transfer.
Operations
List documents visible to the caller
Lists the workspace's documents the caller may read — those they own,
are explicitly shared on (sharedWith), or (as a workspace owner)
manage. This is the default posture
(permissions.enforce_private_docs, on unless disabled). A relay
configured with that setting off returns every document in the caller's
workspace instead. Access is always scoped to the workspace resolved
from the token's wsp claim.
Authorizations
App token verified per token-format.md: an OIDC-issued, RS256-signed
access token validated against the issuer's JWKS. The relay does not
mint or sign tokens.
Responses
Documents the caller has access to.
Fetch a document by id
Authorizations
App token verified per token-format.md: an OIDC-issued, RS256-signed
access token validated against the issuer's JWKS. The relay does not
mint or sign tokens.
Responses
Document.
Save (create or replace) a document
Authorizations
App token verified per token-format.md: an OIDC-issued, RS256-signed
access token validated against the issuer's JWKS. The relay does not
mint or sign tokens.
Parameters
Query Parameters
Optimistic-concurrency guard; 409 if it doesn't match the stored serverVersion.
"int64"Deliberately re-create a tombstoned (deleted) id (JP-375). Without it,
saving a tombstoned id is refused with 410. Gated to the document's
original owner or a workspace admin.
Request Body
Responses
Saved.
Delete a document
Issue a share link for a document
Authorizations
App token verified per token-format.md: an OIDC-issued, RS256-signed
access token validated against the issuer's JWKS. The relay does not
mint or sign tokens.
Request Body
Responses
Share link issued.
Transfer ownership of a document
Authorizations
App token verified per token-format.md: an OIDC-issued, RS256-signed
access token validated against the issuer's JWKS. The relay does not
mint or sign tokens.
Request Body
Responses
Ownership transferred.
Set or clear a document's collection membership
Assigns the document to a single collection (or clears it with
collectionId: null). Write-scoped like a save. Membership rides the
document body's collectionId and surfaces in DocumentMetadata.
Authorizations
App token verified per token-format.md: an OIDC-issued, RS256-signed
access token validated against the issuer's JWKS. The relay does not
mint or sign tokens.
Request Body
Responses
Membership updated.
List a document's recovery points
Recovery points are relay-captured document versions, newest first.
The relay captures them automatically: periodically while a document
is actively edited, when its last participant leaves (skipped if
nothing changed), and before a suspicious zeroing would overwrite
prior state (the JP-180 poison guard). Retention is a bounded
per-document ring. Read-scoped like GET /api/docs/{id}.
Authorizations
App token verified per token-format.md: an OIDC-issued, RS256-signed
access token validated against the issuer's JWKS. The relay does not
mint or sign tokens.
Responses
Recovery points, newest first.
Capture a recovery point now
Captures a recovery point immediately (JP-428) — backs the version
history UI's open-time refresh, so the timeline leads with current
state instead of the last periodic tick. A resident document is
flushed first so the point reflects "now"; state byte-identical to
the newest existing point dedupes to a no-op (captured: false).
Write-scoped like PUT /api/docs/{id}.
Authorizations
App token verified per token-format.md: an OIDC-issued, RS256-signed
access token validated against the issuer's JWKS. The relay does not
mint or sign tokens.
Responses
Capture result.
Fetch a recovery point's content (non-destructive)
Returns the recovery point flattened to a document body, WITHOUT mutating
live state (JP-183) — backs "save/download to local". Read-scoped like
GET /api/docs/{id}.
Authorizations
App token verified per token-format.md: an OIDC-issued, RS256-signed
access token validated against the issuer's JWKS. The relay does not
mint or sign tokens.
Responses
Recovery point content as a document body.
Restore a recovery point as a new document
Writes the recovery point as a NEW document and deletes + tombstones the
source id (JP-183). Owner-scoped (it deletes the source). Connected
clients receive the source's Deleted event (and strand their copy to
Trash) and the new document's Created event.
Authorizations
App token verified per token-format.md: an OIDC-issued, RS256-signed
access token validated against the issuer's JWKS. The relay does not
mint or sign tokens.
Responses
Restored as a new document.
List the workspace's collection definitions
Authorizations
App token verified per token-format.md: an OIDC-issued, RS256-signed
access token validated against the issuer's JWKS. The relay does not
mint or sign tokens.
Responses
Collection definitions (id/name/colour/order), sorted by order,
plus the registry version for the optimistic-concurrency
handshake on PUT.
Replace the workspace's collection definitions (wholesale)
The editor owns the definition set and replaces it whole. Definitions
are presentation metadata (name/colour/order), not membership — a
document's membership is set via PUT /api/docs/{id}/collection.
Duplicate ids are healed keep-first; structural violations (empty or
oversized name/id/colour, more than 200 collections) are rejected
with 400. When expectedVersion is present the write is conditional
on the current registry version — a mismatch returns 409 with the
current state so the caller can rebase; omitted, the write is an
unconditional replace (legacy clients).
Authorizations
App token verified per token-format.md: an OIDC-issued, RS256-signed
access token validated against the issuer's JWKS. The relay does not
mint or sign tokens.
Request Body
Responses
Definitions replaced.
List a collection's document-members (metadata only)
Returns the documents assigned to the collection in the caller's
workspace, as metadata only — never document bodies, Y.Doc state, or
blobs. A browse/list surface for the web collection view, not a
content-read channel. Workspace-scoped from the JWT; an unknown/foreign
collection id yields an empty list (no cross-tenant existence leak).
Authorizations
App token verified per token-format.md: an OIDC-issued, RS256-signed
access token validated against the issuer's JWKS. The relay does not
mint or sign tokens.
Responses
Metadata for the collection's documents.
Server-rendered PNG preview of a document
Server-rendered SVG preview of a document
Issue an anonymous read-only share-token
Reserved. Supersedes /api/docs/{id}/share (legacy) when the
share-link surface lands.
Authorizations
App token verified per token-format.md: an OIDC-issued, RS256-signed
access token validated against the issuer's JWKS. The relay does not
mint or sign tokens.
Request Body
Responses
Share token issued.
Download a blob
On a filesystem backend the relay streams the bytes (200). On an
object-storage backend it ACL-checks the workspace and returns a 302
redirect to a short-lived presigned URL the client fetches directly.
Authorizations
App token verified per token-format.md: an OIDC-issued, RS256-signed
access token validated against the issuer's JWKS. The relay does not
mint or sign tokens.
Responses
Blob bytes (filesystem backend; content type per stored MIME).
Upload a blob through the relay (hash in path must match content)
Proxies the bytes through the relay. This is the upload path for the
filesystem backend; object-storage backends use the presigned flow
(POST /api/v1/blobs/{hash}/upload-url then .../finalize) so bytes go
directly to storage.
Authorizations
App token verified per token-format.md: an OIDC-issued, RS256-signed
access token validated against the issuer's JWKS. The relay does not
mint or sign tokens.
Request Body
"binary"Responses
Blob stored.
Check whether a blob exists
Request a presigned upload (object-storage backend)
Mint a short-lived presigned PUT so the client uploads blob bytes
directly to object storage, bypassing the relay; after the PUT, call
finalize. Returns { "exists": true } when the workspace already holds
the blob (skip upload + finalize). On a filesystem backend the relay
cannot presign and returns 409 — clients then fall back to the proxy
POST /api/blobs/{hash}.
Authorizations
App token verified per token-format.md: an OIDC-issued, RS256-signed
access token validated against the issuer's JWKS. The relay does not
mint or sign tokens.
Request Body
Responses
A presigned upload, or an already-exists marker for a dedup hit.
Ingest a blob from a URL (server-side fetch)
Fetch bytes from url (sending authorization verbatim as the
Authorization header), store them content-addressed for the caller's
workspace, and return the SHA-256 hash. Lets a trusted backend hand the
relay a reference instead of streaming the bytes through itself.
Disabled by default: returns 403 unless the operator configures a
host allowlist ([tenancy.limits] blob_ingest_allowed_hosts /
RELAY_BLOB_INGEST_ALLOWED_HOSTS). The allowlist (exact host or
*.suffix wildcard) is enforced on the initial URL and every redirect
hop; only https is allowed and private/loopback IP-literal hosts are
rejected (SSRF protection). source/tags are opaque provenance
strings recorded for audit; the relay does not interpret them.
Authorizations
App token verified per token-format.md: an OIDC-issued, RS256-signed
access token validated against the issuer's JWKS. The relay does not
mint or sign tokens.
Request Body
Responses
Stored (or deduplicated) blob.
Finalize a presigned upload (object-storage backend)
Confirm a direct upload landed: the relay HEADs the object for its
authoritative size, re-checks the workspace quota (reclaiming the object
and returning 507 if over), then records the blob and grants the
workspace ACL.
Authorizations
App token verified per token-format.md: an OIDC-issued, RS256-signed
access token validated against the issuer's JWKS. The relay does not
mint or sign tokens.
Request Body
Responses
Blob recorded.
The calling workspace's storage usage + effective limits
Workspace-scoped from the validated bearer token — a caller can only
ever read its own numbers. Counts only; no document ids, no content.
storageBytes is the combined meter (docBytes + blobBytes); a
null quota/limit means unlimited / no ceiling.
Authorizations
App token verified per token-format.md: an OIDC-issued, RS256-signed
access token validated against the issuer's JWKS. The relay does not
mint or sign tokens.
Responses
Usage snapshot.
WebSocket upgrade for CRDT sync + awareness
WebSocket endpoint multiplexing SYNC, AWARENESS, AUTH, AUTH_RESPONSE,
JOIN_DOC, DOC_EVENT, and ERROR frames. Protocol version negotiated
on connect — see relay/src/server/protocol.rs and the fixture set
at relay/tests/protocol-fixtures/.
Token verification follows token-format.md. Connections whose
token region does not match the relay's configured region are
rejected with a 403 close.
A JOIN_DOC frame is answered with an ERROR frame (the connection stays
open) when the document is unknown (ERR_UNKNOWN_DOC) or deleted
(ERR_DELETED). A JOIN_DOC for a document the caller may not read is
refused with ERR_VIEW_FORBIDDEN and the client is not joined — the
same owner/share rules the document listing applies. On a relay with
permissions.enforce_private_docs disabled, any authenticated member
of the workspace may join any of its documents.
Live edits are gated separately: a caller who may read but not write
(a view share, or the workspace viewer role) has its write-bearing
SYNC frames dropped with ERR_EDIT_FORBIDDEN while still receiving
state.
Parameters
Header Parameters
Responses
WebSocket upgrade.
MCP Server-Sent Events stream (keep-alive)
MCP JSON-RPC request
Close an MCP session
internal
Server-to-server endpoints, called by the operator's auth control plane.
Not for client use.
Operations
Push a token revocation set update to the relay
Server-to-server. Called by the operator's auth control plane to
push revocations. Authenticated with the shared
revocation_push_bearer secret in relay.toml [auth]
(constant-time compared). See webhooks.md and revocation.md
for the protocol.
Authorizations
Shared bearer secret between the auth control plane and the relay.
Rotated regularly. Not user-facing. See revocation.md.
Request Body
Responses
Applied.
