Skip to main content
The rule, in one sentence: your backend uses the organization API key; your frontend uses a session token. Authentication covers the mechanics of each credential. This page is about the trust boundary between them — what a browser can and cannot be trusted with, and how the design makes the wrong thing unreachable rather than merely discouraged.

Why

An organization API key can do everything: rewrite agents, read tool-provider configuration, mint tokens, run experiments. Before sessions there were two ways to put chat in a browser, and both were bad: ship the key to the page, or proxy every streaming request through your own servers so the key never left them. A session token is the third option. Your backend vouches once — this is user maya, she bills to group acme, these are her CRM credentials — and gets back a short-lived token that carries all three and can change none of them. The browser talks to Sidenet directly with that token, streaming included.

Minting

Only the organization API key can mint. A session token presenting itself to POST /v1/token gets a 403, because a session that could mint sessions would have unbounded lifetime. Expose a small endpoint of your own that mints for the signed-in user and returns the response to the page. Three things are decided at this moment and fixed for the life of the session: Tool credentials are stored on the user, encrypted, not on the token. The token is a reference; the secret never travels to the browser at all. See Authenticating tool providers.

What a session cannot do

Session tokens are confined to the chat runtime by an allow-list of routes, enforced before any handler runs:
  • ChatPOST /v1/chat, the stream resume and cancel endpoints, threads, messages, votes, marking a thread read, running an agent, a network, a workflow or a tool.
  • The user’s own automations — listing their workflows, and creating, reading, editing, pausing, resuming and running their schedules. Every one of these is scoped to the session’s user; anyone else’s answers 404.
  • Widget reads — the network’s configuration, the agent list, the tool list, and the credential-field descriptors from GET /v1/tools-auth.
Everything else returns 403 with a message saying the endpoint needs the organization API key from your backend. That covers every write to organization configuration — agents, workflows, prompt blocks, tool providers — and also reads that would expose configuration, such as GET /v1/tool-providers, which returns provider auth settings even in redacted form. There is deliberately no token value that grants writes to organization configuration. Nor can a session claim another identity. X-User-Id headers, userId fields and runtimeAuth maps in a request body are all ignored under a session token; the API takes user, group and credentials from the session and nothing else.

Refresh

POST /v1/token/refresh takes only the refresh token, no API key and no identity, so the browser can call it directly. Both tokens are replaced on every call and the presented refresh token is spent. The SDK does this for you. Give initSidenet the mint response as authaccess_token, refresh_token, expires_in — and, while a refresh token is present, it refreshes ahead of expiry, retries once if a request still comes back 401, and never interrupts an answer that is streaming: the new credential applies to the next outgoing request. auth is replaced whole when you update it, never merged, and swapping in a session for a different user needs no teardown. See SDK authentication for onRefresh, onError and persisting across reloads.
Refresh tokens are single-use, and the server treats a second presentation of the same one as proof that two holders exist. Don’t run your own refresh loop next to the SDK’s, and keep the pair in sessionStorage rather than localStorage — two tabs sharing one refresh token will revoke the session for both.

Revocation

  • Reuse revokes. Presenting a spent refresh token, or losing the race when two refreshes arrive at once, revokes the entire session with a 401. The client must bootstrap again through your backend; the SDK reports this as a fatal session-revoked error.
  • Revoking the API key kills every session it minted, immediately and with no bookkeeping — session validity is checked against the key on every request.
  • Cached credentials are evicted on revocation, so a revoked token stops working within the same request cycle rather than at the end of a cache window.
Stored tool credentials outlive sessions on purpose, so scheduled workflows keep running between logins. Remove them explicitly with a null entry on PATCH /v1/users/{userId} when a user disconnects an integration or offboards.

Migrating from the API-key embed

SDK versions before 2.0.124 took an organization credential and identity fields in the browser. The session model replaces all of them: The only new piece of infrastructure is the endpoint on your backend that mints. Everything the page used to assert about identity, billing and credentials moves behind it.