Get started

Authentication

Personal access tokens with scopes, AI agents as members of their own, and OAuth for apps that act for people.

Every /v1 call sends a bearer token:

HTTP
GET /v1/spaces HTTP/1.1
Host: side.example.com
Authorization: Bearer ssp_6Jw…

There are three ways to get one, depending on who the program acts for.

ProgramTokenHow
Your script, CI job or servicePersonal access token ssp_…sidespace token create
An AI agent or bot that should appear as itselfA token for an agent membersidespace agent create, then token create --agent
An app that other people sign in toOAuth 2.1 access tokenAuthorization code with PKCE

People sign in to the apps with an email code, or through their organization's identity provider when it has set up single sign-on. A code works once. Sign-in endpoints answer 429 with code rate_limited and a Retry-After header (seconds) when an address or a network has tried too often; after 10 wrong codes in an hour the address is locked for the rest of that hour.

Personal access tokens

Tokens start with ssp_. The server stores only a hash, so a token is shown once. Each token has scopes, can be limited to some spaces, and expires after 90 days unless you choose otherwise (--expires-days 0 never expires).

Shell
sidespace token create "nightly export" --scope files:read --space "Film A"
sidespace token list
sidespace token revoke tok_01JD…

The CLI accepts a token too, with no sign-in: set SIDESPACE_TOKEN=ssp_… or pass --token.

Scopes

ScopeAllows
files:readList spaces, browse, search, read versions and sidecars, download, read notifications
files:writeEverything in files:read, plus upload, create, rename, move, delete and restore
sidecars:writeWrite any sidecar namespace
sidecars:write:<ns>Write one namespace; a trailing * covers a family, e.g. sidecars:write:x-acme.*
renditions:writeUpload thumbnails, proxies and other renditions
events:readRead the journal and realtime signals
shares:manageCreate and revoke share links
members:manageAdd, change and remove members
webhooks:manageManage the space's webhooks (the token's owner must be a space manager)
runs:writeRun actions such as transcribe, AI tags and convert (editor or above)
pipelines:manageManage pipelines (space manager)
plugins:manageInstall, update, turn off and remove plugins (space manager)
comments:writeComment, reply and resolve (commenter or above)
adminAll of the above, plus creating and renaming spaces

A scope never adds to what the person behind the token may do in a space: an admin token of a viewer is still a viewer there.

Tokens can't manage devices, tokens or agents. Those need a signed-in app or CLI, so a token can never mint a stronger token.

Errors you will see

  • 403 with {"error": {"code": "forbidden", "message": "this token needs the files:write scope"}} names the missing scope.
  • 404 for a space outside the token's spaces, exactly like a space that doesn't exist. The API never confirms that a space you can't see exists.
  • 402 with code quota_exceeded when a plan limit stops a save, a new member or an AI run. The message says which limit, on whose plan (a space counts toward its owner's), and when a monthly allowance renews. Show it as is. GET /v1/me/plan (or sidespace plan) returns your own plan, limits and use.

Agents

An AI agent or service account can be a member of its own instead of borrowing a person's identity. Everything it changes is recorded with actor_kind: "agent", and the apps show a purple Agent badge in members, version history and activity.

Shell
sidespace agent create "Clip Tagger"
sidespace members "Film A" --add "Clip Tagger" --role editor
sidespace token create tagger --agent "Clip Tagger" \
  --scope files:read --scope "sidecars:write:x-tagger.*"
sidespace agent rm "Clip Tagger"   # revokes its tokens and removes it from every space

Agents can't sign in with an email code; they act only through tokens. When an agent is removed, its past changes keep its name.

Work the server does itself is marked too. A thumbnail made by media processing is recorded as actor_kind: "plugin", actor_via: "media".

OAuth for apps

Apps that act for other people (a web app, a desktop tool, an MCP client) use the OAuth 2.1 authorization code flow with PKCE, so nobody copies tokens around. Server metadata: /.well-known/oauth-authorization-server.

Register the app:

Shell
sidespace app create "Acme Review" --redirect https://acme.example/oauth/callback
# client_id = app_01…
sidespace app create "Acme Sync" --redirect https://acme.example/cb --confidential   # server-side app, also gets a client_secret
sidespace app list
sidespace app rm app_01…      # every grant stops working at once

Then:

  1. Send the person to /oauth/authorize with response_type=code, client_id, redirect_uri, state, code_challenge, code_challenge_method=S256 and scope (space-separated, e.g. files:read files:write).
  2. They sign in with their email code, choose which scopes and spaces to grant, and are sent back to redirect_uri?code=…&state=…&iss=….
  3. Your app posts a form to /oauth/token: grant_type=authorization_code, code, redirect_uri, client_id, code_verifier. The answer has an access_token (ssp_…, one hour) and a refresh_token (ssr_…, 90 days, replaced at every refresh).
  4. Refresh with grant_type=refresh_token. Sign out with POST /oauth/revoke.
Shell
curl -X POST https://side.example.com/oauth/token \
  -d grant_type=authorization_code -d code="$CODE" -d client_id=app_01… \
  -d redirect_uri=https://acme.example/oauth/callback -d code_verifier="$VERIFIER"
  • Without scope, the default is files:read files:write comments:write runs:write. admin can't be granted to an app, and the person may untick scopes or pick only some spaces.
  • A grant is a token: it appears in the person's sidespace token list as app:… and can be revoked there. Scopes, space limits and the 403/404 rules are the same as for any token.
  • Redirect URIs must be https, loopback http (any port, RFC 8252) or the app's own scheme (cursor://…). Public clients must use PKCE.
  • Apps may also register themselves at POST /oauth/register (RFC 7591, public clients only). MCP clients do this. The consent page says the app registered itself.