API reference

Side Space API v0.1.0

Base URL
https://side.example.com/v1
Block gateway URL
https://blocks.side.example.com

Control-plane REST API of sidespace-server (prefix /v1) and the data-plane API of sidespace-blockgw. This file is the single source of truth for the client/server contract: change it first, then the Go handlers (services/server) and the Rust client (crates/sidespace-apiclient).

  • Auth: Authorization: Bearer <token> on every /v1 call except /v1/auth/* and /v1/openapi.yaml. The token is an app's access token (from /v1/auth/*, full access) or a personal access token ssp_… (see /v1/tokens). A personal access token carries scopes and may be limited to some spaces; a call it does not cover answers 403 naming the scope it needs. Scopes: files:read, files:write (includes read), sidecars:write (every namespace) or sidecars:write:<ns> (one; a trailing * covers a family, e.g. sidecars:write:x-acme.*), renditions:write, events:read, shares:manage, members:manage, webhooks:manage, runs:write, pipelines:manage, plugins:manage, comments:write, admin (everything). Tokens never reach /v1/devices, /v1/tokens or /v1/agents.
  • Agents: an AI agent or service account is a user of kind agent, made by a person (/v1/agents). It joins spaces by its address like anyone, acts only through tokens, and every change it makes carries actor_kind: agent in the journal.
  • For AI agents, a short guide: /llms.txt. AI agents can also connect to the remote MCP server at /mcp (streamable HTTP, JSON answers) with the same bearer token: tools list_spaces, search, list_folder, describe_file, read_text, write_text, get_sidecar, put_sidecar, list_versions, restore_version, recent_changes, list_actions, run_action, get_run, each checked against the token's scopes and spaces.
  • Actions and runs: an action does one thing to one version of a file: side.transcribe (transcript sidecar), side.tags (ai.tags sidecar), side.convert (a new file next to it, with a derived sidecar). GET /v1/spaces/{sid}/actions lists them and whether this server is set up for them. A run is one action on one version; results are cached by content, so the same bytes with the same params are done once (cached: true). Pipelines run an action on every new file matching a path glob and MIME prefix. Plugins (/v1/spaces/{sid}/plugins) add third-party actions: HTTPS services that get signed jobs (PluginJob) and answer with a PluginResult, at once or later through /v1/plugin-runs/{rid}/… with the job's callback token (ADR 0015). Changes made by runs carry actor_kind: plugin and actor_via: <action>, and never start pipelines again.
  • Errors: {"error": {"code": "...", "message": "...", "details": {...}, "request_id": "req_…"}} with a matching HTTP status. A space the caller is not a member of answers 404, never 403. Every answer carries X-Request-Id and Sidespace-Version headers.
  • Safe writes: send If-Match: "ver_…" with the version you read (commit, delete, restore, rename) or If-None-Match: * to write only where nothing is yet; a write that would overwrite someone else's save answers 412 precondition_failed instead. The S3 gateway takes If-Match: "<etag>", If-None-Match: * and x-sidespace-if-version: ver_… on PutObject, CopyObject, CompleteMultipartUpload and DeleteObject.
  • History: as_of (a time, "-2h" or a journal seq) reads paths, nodes and folders as they were; POST …/nodes/{nid}/rewind puts a folder back. Over S3 every bucket is versioned: ListObjectVersions, GetObject/HeadObject versionId, copy ?versionId= to restore, trash shows as delete markers (del.<node id>; deleting one brings the file back), and x-sidespace-as-of lists or reads the bucket as it was. PUT bucket makes a space (with x-sidespace-fork-source: <bucket>[/<folder>], a fork); DELETE bucket deletes a space that never held anything.
  • Lists: ?cursor=&limit=; responses carry next_cursor (null on the last page).
  • Webhooks: a space manager subscribes a URL to the space's journal (/v1/spaces/{sid}/webhooks). Each event is one signed POST (WebhookEvent), in journal order; failures retry with backoff (10 s doubling to 1 h; 24 failures in a row turn the subscription off). Side-Signature: t=<unix>,v1=<hex HMAC-SHA256(secret, "<t>.<body>")>; dedupe on Side-Event-Id.
  • IDs: prefixed ULIDs (usr_, dev_, spc_, nod_, ver_, shr_, ntf_, tok_, whk_, run_, pip_, plg_).
  • Hashes: BLAKE3, 64 lowercase hex characters.