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:
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.
| Program | Token | How |
|---|---|---|
| Your script, CI job or service | Personal access token ssp_… | sidespace token create |
| An AI agent or bot that should appear as itself | A token for an agent member | sidespace agent create, then token create --agent |
| An app that other people sign in to | OAuth 2.1 access token | Authorization 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).
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
| Scope | Allows |
|---|---|
files:read | List spaces, browse, search, read versions and sidecars, download, read notifications |
files:write | Everything in files:read, plus upload, create, rename, move, delete and restore |
sidecars:write | Write any sidecar namespace |
sidecars:write:<ns> | Write one namespace; a trailing * covers a family, e.g. sidecars:write:x-acme.* |
renditions:write | Upload thumbnails, proxies and other renditions |
events:read | Read the journal and realtime signals |
shares:manage | Create and revoke share links |
members:manage | Add, change and remove members |
webhooks:manage | Manage the space's webhooks (the token's owner must be a space manager) |
runs:write | Run actions such as transcribe, AI tags and convert (editor or above) |
pipelines:manage | Manage pipelines (space manager) |
plugins:manage | Install, update, turn off and remove plugins (space manager) |
comments:write | Comment, reply and resolve (commenter or above) |
admin | All 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
403with{"error": {"code": "forbidden", "message": "this token needs the files:write scope"}}names the missing scope.404for 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.402with codequota_exceededwhen 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(orsidespace 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.
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 spaceAgents 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:
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 onceThen:
- Send the person to
/oauth/authorizewithresponse_type=code,client_id,redirect_uri,state,code_challenge,code_challenge_method=S256andscope(space-separated, e.g.files:read files:write). - They sign in with their email code, choose which scopes and spaces to grant, and are sent back to
redirect_uri?code=…&state=…&iss=…. - Your app posts a form to
/oauth/token:grant_type=authorization_code,code,redirect_uri,client_id,code_verifier. The answer has anaccess_token(ssp_…, one hour) and arefresh_token(ssr_…, 90 days, replaced at every refresh). - Refresh with
grant_type=refresh_token. Sign out withPOST /oauth/revoke.
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 isfiles:read files:write comments:write runs:write.admincan'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 listasapp:…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.