Sessions for the browser

Give your frontend a short-lived token that acts as one user, so your secret key never leaves your server.

Your API key can do anything in your account, so it stays on your server. When code running in a user's browser needs to call NoClick directly (to run an agent chat, show a connect button, or list their inbox), your server mints a session: a token that acts only as that user, with only the scopes you give it, for a short time.

Mint a session on your server

import noclick

def session_for(user_id: str) -> dict:
    user = noclick.User.from_id(user_id)
    session = user.session(["agents", "humans", "credentials:request", "credentials:use"], ttl_s=3600)
    return {"token": session.token, "expires_at": session.expires_at.isoformat()}

Return the token to your frontend, which uses it the way it would use an API key. The token starts with nk_sess_, and a session's repr never prints it.

A session can hold any of these scopes, as long as the key that minted it has them too:

ScopeLets the browser
agentsmessage the user's agents and read their conversations
humanssend the user's own requests and read them
credentials:requestcreate the user's connections and send their connect links
credentials:uselist and read the user's connections and run operations through them
channelsopen, post in and read the user's channels
inboxcreate and read the user's inboxes
aicall AI models, charged to your account and counted toward the user's spend cap

Sessions never create keys, sessions or users, and never change policy, brand or the user's spend cap. Those stay with your secret key. A session with agents can create agents for its user, though, and set their budgets. And any session may move its own user's timezone, with user.update(timezone=...) (PATCH /v1/users/{id} with timezone alone), so a user who travels can say where they are; it can't read or change anything else about them.

How long a session lasts

ttl_s is between 60 seconds and 24 hours, one hour by default. session.expired tells you whether it has run out by your machine's clock. Revoking the key that minted a session revokes the session too.

Mint a fresh session when your page loads instead of storing one. The call is cheap: User.from_id makes no request of its own, so minting a session is a single call.

Use a session from your server

A session can also drive the SDK on your server, which is handy for testing exactly what your frontend is allowed to do:

as_ana = noclick.Client.for_session(session)   # or session.client()
noclick.Agent.list(client=as_ana)              # Ana's agents and the shared ones, nothing else

Calling from the browser

The API answers cross-origin requests from any origin, with the token as a bearer and no cookies. The TypeScript client takes the token with NoClick.forSession(token).