Skip to main content
There are two credentials, and one rule for choosing between them: Your backend uses the organization API key. Your frontend uses a session token. The API key can rewrite your agents and read your tool-provider configuration, so it must never reach a browser. When you need to call Sidenet from client-side code, exchange it for a session token — a short-lived credential scoped to one end user and to the chat runtime. If you call Sidenet only from your own servers, the API key is all you need and nothing below changes for you.

Bearer token

All routes require a bearer token. Send it in the Authorization header:
In the API Reference “Try it” panel, paste your token into the Authorization field and it is sent automatically.

Organization context

Requests are scoped to the organization your API key belongs to. There is nothing extra to send — the key already identifies the org.

Which credential does each endpoint take?

Every reference page states what it accepts under Authorization. There are three classes:

User identity

User identity travels in the session token: your backend mints one for an end user, and every request made with it is that user — from a browser or from a server. User-scoped resources resolve to {orgId}_{userId}. Nothing else is sent to identify the user, and organization-scoped endpoints don’t need an identity at all.

Session tokens (for browsers)

A session token lets client-side code call the chat endpoints without holding your API key. Your backend vouches once for who the end user is, which group they bill to, and which tool credentials they may use; the browser gets back a token that carries all of that without being able to change any of it.

1. Mint a token on your server

Only user_id is required. An omitted group_id bills the session to the user’s current group — whatever a previous mint, chat call, or PATCH /v1/users/{userId} set — falling back to your organization’s Default group. The mint takes ids only: display names for users and groups are set on the update routes. Send only access_token to the browser if it has no need to refresh, or both if it does.
The group fallback is silent. If you bill per team, send group_id explicitly (or keep users current via PATCH /v1/users/{userId}) — a user whose group was never set bills to the Default group without an error.

2. Call the chat endpoints from the browser

Note what is not in that request: no API key and no identity fields. The user, the group and the tool credentials all come from the session. Anything identity-shaped the browser sends is ignored, which is the point — a client cannot claim to be a different user, bill a different group, or substitute its own credentials.

3. Refresh when the access token expires

Safe to call directly from the browser — it takes no API key and no identity fields. Both tokens are replaced each time and the old refresh token is spent.
Refresh tokens are single-use. Presenting one that has already been spent means two holders exist, so the entire session is revoked and the call returns 401. When that happens, bootstrap again through your backend.

What a session token can reach

Session tokens are scoped to the chat runtime: POST /v1/chat · GET|DELETE /v1/chat/stream · GET /v1/threads · POST /v1/threads/{id}/read · GET /v1/messages · POST /v1/vote · POST /v1/agents/{id}/run · POST /v1/copilots/{id}/run · POST /v1/workflows/{id}/run · POST /v1/tools/{toolId}/execute · GET /v1/copilots/{id} · GET /v1/agents · GET /v1/agents/{id} · GET /v1/tools · the user’s own workflow schedules and runs (/v1/workflow-schedules…, /v1/workflow-runs…) Everything else — creating or editing agents, workflows, prompt blocks and tool providers — returns 403 and requires the API key from your backend. There is no token that grants write access to your organization’s configuration.

Tool credentials (tools_auth)

tools_auth is a map keyed by tool provider id, each entry carrying the provider’s credentials (plus an optional base_url override):
Credentials persist on the user, not on the session: everything the user touches — their sessions, workflow runs, scheduled workflows — reads the same stored credentials, and a later mint inherits them without re-sending. Each push replaces only the providers it names; delete one by sending a null entry to PATCH /v1/users/{userId} (e.g. when the user disconnects an integration). GET /v1/tools-auth lists your organization’s providers and the credential fields each one expects — call it when building the map. Runtime auth is organization-scoped, so the list is the same for every copilot (the GET /v1/copilots/{id} read also bundles it as runtimeAuthProviders).

Lifetimes and revocation

Revoking the API key that minted a session ends that session immediately, along with every other session minted from that key. Stored tool credentials outlive sessions — remove them with null entries on PATCH /v1/users/{userId} when a user offboards or disconnects an integration.
Credentials in tools_auth are encrypted at rest and injected server-side when the agent calls a tool. They are never returned by any endpoint, never logged, and never used as part of a cache key — including by the endpoints that accept them.

Updating a user without re-minting

Everything the mint call vouches for can be changed later, from your backend, while the browser keeps the session token it already holds: PATCH /v1/users/{userId} updates the user’s display name, their per-provider tool credentials, and/or their group. Users can also be created ahead of use with POST /v1/users — same fields plus the id — so their group, name and credentials are in place before their first session. Like groups, creating explicitly is optional: a mint with an unseen user_id provisions the user automatically.
All fields are optional (send at least one). Credentials persist on the user, and every surface — live sessions, workflow runs, scheduled workflows — reads through the same store, so a push here reaches all of them within a minute. Only the providers you send are touched; a null entry deletes that provider’s stored credentials. This is the endpoint to reach for when an end user’s upstream token is short-lived, when they move teams, when they disconnect an integration, or when their scheduled workflows should keep running with fresh credentials between logins. Like the mint call, it takes the org API key and must be called from your backend — a session token cannot call it.

Groups

A group is the unit users belong to — today it is what billing and spend caps attach to. Create one ahead of use with POST /v1/groups, so its cap is in place before the first user references it:
Creating explicitly is optional: minting a token or updating a user with an unseen group id provisions the group automatically, with a default cap. Either way, PATCH /v1/groups/{groupId} renames a group or changes its cap later:
The cap is enforced per calendar month; null removes it.

Errors