Embed AI Assistants & Dashboards
Put a governed Colrows AI Assistant or Dashboard directly inside your own application. An AI Assistant uses delegated embed sessions: your server vouches for the signed-in user, and Colrows issues a short-lived token for that user. A restricted Dashboard uses a Colrows user session token, and a public Dashboard needs no token. This guide covers all three, plus the security model and troubleshooting.
Integration overview
This page is the full embedding walkthrough. For how authentication works across every Colrows surface, see the Authentication reference.
| Embed | How the viewer authenticates | Viewer needs a Colrows account? |
|---|---|---|
| AI Assistant | A delegated embed session. Your server identifies the signed-in user and requests a five-minute embed token; the loader renews it automatically. | No. Colrows creates an embedded user for each of your users. |
| Restricted Dashboard | A Colrows user session token for the viewing user. | Yes |
| Public Dashboard | None. Anyone with the URL can render it once the owner enables public sharing. | No |
A server-to-server OAuth client token (cr_sem_at_…) is for the Semantic API, data access and data masking policies, and the agent interface. It cannot open a dashboard or start a chat, and is rejected with 403. The old dashboard:read scope has been removed. AI Assistants use delegated embed sessions, and restricted Dashboards use a user session token.
Examples use https://cloud.colrows.com. Substitute your deployment's {COLROWS_BASE_URL} where relevant. All requests must use HTTPS.
POST /api/integration/login and organization API keys no longer exist. Move an AI Assistant embed to a delegated embed session and a Dashboard embed to a user session token, as described below.
Part 1 - Embed an AI Assistant
An embedded AI Assistant chats on behalf of a user who signed in to your application, not to Colrows. Your server tells Colrows who that user is, and Colrows issues a short-lived embed token for them. The browser never sees a long-lived credential.
- A Colrows administrator registers an integration for one Assistant and one parent origin, and gets an integration ID and secret.
- Your server exposes an authenticated endpoint that exchanges the secret and the signed-in user's ID for an embed session.
- The page loads
embed.js, which calls that endpoint, hands the session to the Assistant iframe, and renews it before it expires.
Configure an assistant
- Open Administration → Assistants.
- Select + Assistant.
- Enter a unique name.
- Select the datasource the assistant must use. This binding is required for embedded chat.
- Optionally select a schema. The embedded chat is then limited to that schema.
- Optionally provide styling configuration.
- Optionally declare User context fields the host page may send (see Pass page context), then save.
- Use the assistant's How to Use action to obtain its assistant ID and embed examples.
If the assistant API returns datasource: null, edit the assistant and bind an active datasource. Otherwise embedded chat shows Please select datasource to proceed.
Step 1 - Register an integration
An organization administrator calls this endpoint with their normal Colrows bearer token. There is no screen for it yet.
POST /api/embed/integrations
Authorization: Bearer <administrator session token>
Content-Type: application/json
{
"name": "Acme application",
"assistantId": "ASSISTANT_ID",
"parentOrigin": "https://app.acme.example",
"expiresAt": 1798761600000
}
parentOriginis the exact HTTPS origin of the page that hosts the Assistant, with no path, query or fragment. Colrows allows framing only from this origin.expiresAtis in epoch milliseconds, in the future and at most one year away.- One integration covers one Assistant and one origin. Register a separate integration for each application or origin.
The response returns the secret once. Colrows keeps only its SHA-256 hash, so store it in your server's secret store straight away.
{
"integrationId": "cr_embed_client_…",
"integrationSecret": "…",
"assistantId": "ASSISTANT_ID",
"parentOrigin": "https://app.acme.example",
"expiresAt": 1798761600000
}
Step 2 - Add a session endpoint to your server
Your server calls POST /api/embed/sessions with the integration secret and the ID of the user who is signed in to your application. Expose it to your own front end as an authenticated endpoint, for example /api/colrows-assistant-session.
// Your server (Node.js and Express shown). requireLogin and verifyCsrf are your own middleware.
app.post("/api/colrows-assistant-session", requireLogin, verifyCsrf, async (req, res) => {
const response = await fetch("https://cloud.colrows.com/api/embed/sessions", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.COLROWS_INTEGRATION_SECRET}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
integrationId: process.env.COLROWS_INTEGRATION_ID,
externalUserId: req.user.id // from your server session, never from the browser
})
});
res.set("Cache-Control", "no-store");
res.status(response.status).json(await response.json());
});
The session response:
{
"token": "cr_embed_…",
"userId": "…",
"orgId": "…",
"integrationId": "cr_embed_client_…",
"assistantId": "ASSISTANT_ID",
"parentOrigin": "https://app.acme.example",
"expiresAt": 1790000000000
}
- Take
externalUserIdfrom your authenticated server session, and apply your own access checks and CSRF protection before calling Colrows. Use a stable ID (up to 256 characters), not an email address that can change. - The first call for an external ID creates an embedded user in Colrows: no password, no administrator access, and never linked to an existing Colrows account by email. Later calls reuse the same user. The same external ID under another integration or organization is a different user.
- The token lasts five minutes, or until the integration expires if that is sooner. There is no refresh token: the loader asks your endpoint for a new session instead, so your server re-checks the user's own session every time.
Step 3 - Load the Assistant
<div id="colrows-assistant" data-assistant-id="ASSISTANT_ID"></div>
<script src="https://cloud.colrows.com/embed.js"></script>
<script>
const assistant = AssistantChat.init({
containerId: "colrows-assistant",
baseUrl: "https://cloud.colrows.com",
integrationId: "INTEGRATION_ID",
theme: "light",
getSession: async () => {
const response = await fetch("/api/colrows-assistant-session", {
method: "POST", credentials: "same-origin"
});
if (!response.ok) throw new Error("Could not start the Assistant session");
return response.json();
},
onError: error => console.error(error.message)
});
</script>
- The iframe URL carries only the public integration ID and the page's origin. The session travels by
postMessage, and both sides check the sender window and the exact origin. - The loader checks every session before passing it on: the token must start with
cr_embed_, and the Assistant, integration and origin must match. A mismatch is reported throughonError. - The iframe keeps the token in memory only and asks for a new session 30 seconds before it expires.
- The loader adds a chat button in the bottom-right corner that opens and closes the Assistant.
Sign-out and removal
- Call
assistant.logout()when the user signs out of your application. It clears the iframe and callsPOST /api/embed/logoutto revoke the current token. - Call
assistant.destroy()to remove the widget without a server request. The current token then expires within five minutes.
Pass page context
Add a context object to AssistantChat.init to tell the Assistant what the user is looking at, such as the current customer or region. The loader forwards it, and it is sent with the new conversation.
Each key must be declared as a User context field on the Assistant, with a name, a type (string, boolean, number, integer, or array), a description, and whether it is optional. Colrows rejects a new conversation whose context has an undeclared key, misses a required field, or has a value of the wrong type. The example below needs page and region declared as string fields.
AssistantChat.init({
// ...the options above
context: { page: "account-overview", region: "EMEA" }
});
Context is untrusted input. It helps the Assistant interpret questions, but it never grants or limits data access. Embedded sessions cannot set widgetId or widgetType.
What an embedded user can do
- Chat with the integration's Assistant, on its datasource and, if one is set, its schema.
- See and delete only their own conversations with that Assistant.
- Nothing else: an embed token cannot create Assistants, manage users, change data policies, save datasets or use the general query API.
Data access policies apply to the embedded user's Colrows user ID. Colrows does not infer row access from the external ID or from page context, so configure data access and data masking policies for embedded users the same way you do for anyone else. See Data Access Control.
Manage integrations
| Task | Endpoint |
|---|---|
| List integrations | GET /api/embed/integrations |
| Revoke an integration | DELETE /api/embed/integrations/{integrationId}. Its existing embed tokens stop working on their next request. |
| Replace a secret | Create a new integration, switch your server to it, then revoke the old one. A new integration has its own set of embedded users, so earlier chat history stays with the old one. |
All three require an organization administrator.
For users who already have Colrows accounts, existing embeds that pass a user session token (token in AssistantChat.init, or ?token= on /chat/{assistantId}) remain supported for compatibility. Use delegated sessions for new embeds: they need no Colrows account per user, never put a long-lived token in the browser, and restrict framing to your registered origin. Do not pass a cr_embed_ token through the token option; the loader rejects it and asks for getSession.
Part 2 - Embed a Dashboard
Open the dashboard's action menu and select Embed to obtain its dashboard ID and integration examples.
Get a user session token
A restricted Dashboard embed runs as a Colrows user, so your application supplies a Colrows user session token for the person viewing it. A public Dashboard skips this step. Obtain the token the way the viewer signs in to Colrows: an interactive sign-in (POST /api/user/login) or your configured SSO (SAML or OIDC, including Google and Microsoft). See Authentication.
Colrows uses the token as-is. It removes the token from the visible iframe URL and keeps it only in the embed's browser tab, and it does not exchange or refresh it, so supply a fresh token before the current one expires. One active token can serve several dashboard embeds on the page.
Choose the access mode
| Dashboard mode | Token | Behavior |
|---|---|---|
| Public | Not required | Anyone with the embed URL can render it. The owner must enable public sharing first. The dashboard renders the owner's data with per-viewer access and masking rules bypassed, so publish publicly only data fit for anyone with the link. |
| Restricted | Required | Needs a Colrows user session token for a user the dashboard is shared with. OAuth client and MCP tokens are rejected with 403. See the rules below. |
Public dashboard iframe
<iframe
src="https://cloud.colrows.com/embed/dashboard/DASHBOARD_ID?theme=light&access=public"
title="Colrows Dashboard"
width="100%"
height="800"
frameborder="0"
style="border: 0;">
</iframe>
If the dashboard is not enabled for public sharing, this embed fails rather than falling back to authenticated access.
What a restricted embed can see
- A restricted embed renders as the user whose session token you supply. It shows only what that user is allowed to see, with that user's own data access and masking rules applied on every render.
- The dashboard opens only if it is shared with that user, or with a group the user belongs to, or has its public link turned on. A user cannot open a dashboard that is not shared with them.
- If the user's access depends on directory (AD) groups, those groups come from the user's most recent Colrows sign-in. See Authentication.
A public embed instead renders the owner's data with per-viewer access and masking bypassed - treat its contents as public.
Restricted dashboard iframe
Supply the viewing user's session token as token. The loader uses authenticated mode when a token is present and public mode when it is omitted.
<iframe
id="colrows-dashboard"
title="Colrows Dashboard"
width="100%"
height="800"
frameborder="0"
style="border: 0;">
</iframe>
<script>
const url = new URL(
`/embed/dashboard/${encodeURIComponent(dashboardId)}`,
"https://cloud.colrows.com"
);
url.searchParams.set("theme", "light");
url.searchParams.set("access", "authenticated");
url.searchParams.set("token", colrowsToken);
document.querySelector("#colrows-dashboard").src = url.toString();
</script>
Dashboard JavaScript loader
<div id="colrows-dashboard" data-dashboard-id="DASHBOARD_ID"></div>
<script src="https://cloud.colrows.com/dashboard-embed.js"></script>
<script>
DashboardEmbed.init({
containerId: "colrows-dashboard",
baseUrl: "https://cloud.colrows.com",
theme: "light",
// Omit token only when the dashboard is public.
token: colrowsToken
});
</script>
The loader selects authenticated mode when token is present and public mode when it is omitted.
Part 3 - Security
AI Assistant embeds
- Keep the integration secret on your server. It never goes to the browser, and anyone holding it can start sessions for any external user ID.
- Take the external user ID only from your authenticated server session, and protect the session endpoint with your own login and CSRF checks.
- Return sessions with
Cache-Control: no-store. Embed tokens last five minutes and are held in memory by the iframe. - Colrows frames the Assistant only on the integration's registered origin, using CSP
frame-ancestors. Missing, revoked, expired or mismatched integrations cannot be framed. - Call
assistant.logout()when your user signs out, and revoke an integration you no longer use. - Grant data access to embedded users through data access and data masking policies. Page context never changes what they can see.
Dashboard embeds
- Issue the user session token on your trusted backend, for the user viewing the embed. Never mint it in untrusted frontend code.
- Treat the token as a credential even though Colrows removes it from the visible iframe URL, and do not log complete iframe URLs containing tokens.
- User session tokens expire and Colrows does not refresh them. Supply a fresh token and reload the embed before the current one expires; see Authentication.
- Restrict production
frame-ancestorsto approved client origins where possible. - Public dashboards expose their rendered content, with per-viewer access and masking bypassed, to anyone with the URL.
Use HTTPS for both Colrows and the embedding application.
Part 4 - Troubleshooting
AI Assistant embeds
| Symptom | Likely cause | Action |
|---|---|---|
invalid_request (400) when registering | Missing name or Assistant, an expiry in the past or more than a year away, an unknown Assistant, or a parent origin that is not a bare HTTPS origin | Fix the field named in message. Use https://host[:port] with no path |
invalid_client (401) from /api/embed/sessions | Wrong integration ID or secret, or the integration is revoked or expired | Check your server's stored ID and secret, or register a new integration |
invalid_request (400) from /api/embed/sessions | Missing or over-long externalUserId, an Assistant with no datasource, or an inactive embedded user | Send a stable ID of up to 256 characters, and bind an active datasource to the Assistant |
onError: "The embed session is invalid." | The session's Assistant, integration or origin does not match the page, or it has already expired | Make sure the integration was registered for this page's exact origin and this Assistant |
invalid_token (401) during chat | The embed token expired, was logged out, or its integration changed or was revoked | Check that your session endpoint still answers, so the loader can renew; register a new integration if it was revoked |
| Browser refuses to frame the Assistant | The page's origin differs from the integration's parentOrigin, for example www versus the bare domain, or a different port | Register an integration for the exact origin |
| New conversation fails with "Unknown context field", "Required context field ... is missing", or "must be of type" | The page's context does not match the Assistant's declared User context fields | Declare every key you send, send every required field, and match each declared type |
| Assistant asks to select datasource | Assistant datasource reference is missing or inactive | Edit the assistant and bind an active datasource |
Dashboard embeds
| Symptom | Likely cause | Action |
|---|---|---|
INVALID_AUTH_HEADER (401) | The user session token is missing, malformed, expired, or revoked | Supply a fresh user session token and reload the embeds |
INCORRECT_SESSION_INFO | The user session token is no longer active | Get a new user session token and reload the embeds |
INSUFFICIENT_PRIVILEGE (403) | An OAuth client or MCP token was used, or the user lacks access to the dashboard | Use a user session token for a user the dashboard is shared with. OAuth client tokens cannot open dashboards or chats. |
| Restricted dashboard fails | Missing token, the dashboard is not shared with the token's user, or a client or MCP token was used | Supply a user session token, and share the dashboard with that user or a group they belong to |
| Public dashboard fails | Public sharing is disabled | Enable public sharing or use restricted embedding with a token |
| Browser refuses to frame Colrows | Deployment framing headers do not allow the embed route or client origin | Verify X-Frame-Options and CSP frame-ancestors on the embed response |
Integration checklist
AI Assistant
- Create the Assistant, bind an active datasource (and schema if needed), declare any context fields your page sends, and note its assistant ID.
- Have an administrator register an integration for the Assistant and your page's exact HTTPS origin; store the secret on your server.
- Add an authenticated, CSRF-protected session endpoint that calls
POST /api/embed/sessionswith your user's stable ID and returns the response withCache-Control: no-store. - Load
embed.jswithintegrationIdandgetSession, and calllogout()on sign-out. - Configure data access and data masking policies for embedded users.
Dashboard
- Obtain its dashboard ID and decide public or restricted access; share restricted dashboards with the users or groups who will view them.
- For restricted access, obtain a Colrows user session token for the viewing user on your backend and pass it to the iframe or loader; supply a fresh one before it expires.
- Confirm production origin, framing, permissions, and token-handling policies.
For the full programmatic surface, see the HTTP API and REST API reference. Building an agent instead of an embed? Connect over the MCP integration.