Implement the bind endpoint
Binding is a server-to-server call your backend makes to DioscHub. This page is the exact contract.
The two hops
Section titled “The two hops”-
The widget calls your backend. When the widget needs identity, it posts the connection id to a bind endpoint you host, including your app’s session cookie:
POST /diosc/bind (your endpoint)Cookie: <your app's session cookie>{ "wsId": "<connection id from the widget>" }You configure the widget with this endpoint’s URL; see Frontend integration.
-
Your backend calls DioscHub. Your endpoint reads your own session to learn who the user is, then calls DioscHub server-to-server:
POST /auth/bind (DioscHub)x-api-key: <secret admin API key with the auth:bind scope>Content-Type: application/json{"wsId": "<connection id>","identity": {"userId": "user-42","role": { "id": "role-support", "name": "Support agent" }},"authArtifacts": {"headers": { "Authorization": "Bearer <token to forward to MCP servers>" },"cookies": { "session": "<optional cookie to forward>" }}}
The request fields
Section titled “The request fields”| Field | Required | Meaning |
|---|---|---|
wsId | Yes | The widget connection to bind. DioscHub rejects an unknown or absent wsId. |
identity | No | Who the user is. Omit or send null for an anonymous binding. |
identity.userId | With identity | Your app’s stable id for the user. DioscHub records it as the session’s external user id — it is what ties a Session to a real person. |
identity.username | With identity | A display name for the user. |
identity.role | With identity | The Role { id, name } this user maps to — it selects the tools, prompt, budget, and features that apply. |
authArtifacts.headers | Yes | The header map to forward to your MCP servers on each call. |
authArtifacts.cookies | No | Cookies to forward, delivered to your MCP servers folded into a Cookie header. |
Two things you do not send: the assistant, and any tool scope. DioscHub derives which
Assistant applies from the connection itself (the widget declared it
when it connected), and it resolves the user’s tools and features server-side from the role you pass.
The response
Section titled “The response”POST /auth/bind returns 200 { "ok": true }. That is an acknowledgement, not the payload.
The identity, resolved features, and the widget’s REST token are delivered to the widget over its live connection, not in the HTTP response your backend receives. Your backend’s job ends at a successful acknowledgement; the widget learns it is ready on its own channel.
Ownership: one user cannot bind onto another’s connection
Section titled “Ownership: one user cannot bind onto another’s connection”Two protections keep binding safe:
- The assistant scope comes from the connection, never from the caller. Because DioscHub reads the Assistant from the socket’s own validated metadata rather than from the bind request, a caller cannot redirect a connection to a different Assistant.
- A resumed session must belong to the bound user. When a bind lands on a connection whose earlier session is being resumed, DioscHub proceeds only if that session’s external user id matches the user now being bound. A bind for user B cannot silently resume user A’s conversation.
To tear a user’s bindings down — on sign-out, say — call POST /auth/invalidate with
{ "userId": "<id>" }. DioscHub drops every connection’s binding for that user and signals the affected
widgets that they need to bind again.
The REST token
Section titled “The REST token”When you bind a real identity, DioscHub issues the widget a short-lived REST token and delivers it
over the connection alongside the ready signal. The widget uses it as Authorization: Bearer <token> on
its own REST calls to DioscHub, and DioscHub rotates it before it expires.
You do not handle the REST token — it is minted, delivered, and rotated for the widget automatically. Two properties are worth knowing:
- It is scoped to the live connection: it is only valid while that connection’s binding stands. A re-bind supersedes any older token, and a disconnect invalidates it.
- An anonymous binding gets none. The REST token is a signed-in-user credential.