The flow
1
Your backend asks for a session
With a server-side API key, naming the tenant it has already authenticated in your own system. With Or against the endpoint directly:
@devicai/sdk:2
You hand the token to the page
In the response to your own login, in a cookie, wherever your session already lives.
3
The widget uses it
Every Devic call carries the session token. The tenant comes from inside it, so no parameter can override it.
/api/v1/tenant-sessions is the one public route where the /api prefix is required — the gateway serves this endpoint itself instead of proxying it. The SDK handles that for you.What the token can and cannot do
A session is a narrowed copy of the API key’s own token: same account, same role, plus the tenant it is confined to. Everything downstream behaves as it did with the key — only the reach changes, which is what a session should be. What it reaches is an explicit list, closed by default:Allowed
Talk to an assistant, read its own conversations, follow a run, upload attachments, dictate, read and edit the assistant’s memory about it, see its own usage, manage its own connected apps.
Refused
Create assistants or agents, read costs, manage tool servers or projects, administer tenants, touch workspace integrations or the account’s plans.
The list matches segment by segment, not by prefix. A rule over
/v1/assistants/* written as a prefix would also grant DELETE /v1/assistants/{id} — precisely what the list exists to prevent. A new public endpoint is therefore born closed until it is deliberately added.Lifetime
One hour by default, clamped to between 60 seconds and 12 hours. Asking for a year gets you twelve hours rather than an error. The upper bound is a working day on purpose. The useful pattern is not always “refresh every few minutes”: you can issue the session inside your own login and hand it over in a cookie, with no endpoint to refresh it from — and then it has to last as long as the work session does.Two rules that keep it honest
Revocation
Sessions are signed and expire on their own, but you do not have to wait for that. Every call made with a session re-checks that the key that issued it is still active, so disabling the key ends its sessions within seconds. Deleting a key does the same — otherwise deletion would be a suggestion.Usage made with a session is attributed to the key that issued it, so moving from raw keys to sessions does not empty your usage metrics.
In the widget
@devicai/ui takes a session instead of an API key, and can refresh it before it expires:
apiKey in that snippet, and there should not be: a page using sessions has no reason to carry a key.
See Embedding in your product.
Making it impossible to get wrong
Everything above is a convention until the key cannot do anything else. An API key has an identity mode:
Put the session-minting key on
signed and the mistake stops being possible: nobody can paste that key into a page and reach a customer’s data with it, because the only thing it can do is ask for a token that pins the customer. Anything else your server does needs a second key left on open — two keys, two jobs. See API keys.