Skip to content
AskTable

Documentation feedback

Current pageUser-identity embedding/en/integrations/user-embed

0 / 5,000

Your feedback will be sent to the maintenance team.

Go to console
Go to console
AskTable
Go to console

Integrations and development

Embed conversations and workspaces with user identity

Embed a conversation or project workspace in your website using the current user's AskTable identity.

User-identity embedding puts AskTable pages into your website using the current user's own AskTable identity: organizations, projects, and data permissions are the same as when the user signs in to AskTable directly. It suits internal platforms and enterprise portals.

When visitors do not sign in and share one data scope, use anonymous embedding instead.

Guide location: project sidebar → “Agent integrations” → “Integrate AskTable in business systems” → “iframe”.

Choose a mode

ModeSuitsPage scope
ChatAdding conversations to an existing business page, with your website managing the conversation listOne conversation of the current user
WorkspacePutting the AskTable workspace into an internal platform or portalThe project workspace in a specified organization, with project switching

Both modes need the current user's AskTable user credential (user_token). Your platform must first exchange it for the user's AskTable credential through an existing sign-in or single sign-on flow. Do not use an API key or a shared administrator credential to represent all users.

Chat

  1. Prepare the AskTable website address, organization ID, project ID, agent ID, and the current user's credential.

  2. Call the API to list the user's own conversations, or create a conversation for an agent, and get the conversation id:

    GET /api/v1/conversations?created_by_me=true&types=chat&page=1&size=20&sort=modified_desc
    Authorization: Bearer <current user's AskTable credential>
    X-Project-Id: <project ID>
    POST /api/v1/conversations
    Authorization: Bearer <current user's AskTable credential>
    X-Project-Id: <project ID>
    Content-Type: application/json
    
    {"type":"chat","data_agent_id":"<agent ID>"}

    The examples use the all-in-one deployment's /api prefix; for Cloud and other deployments, replace it with the actual API address.

  3. Build the address with the conversation ID and pass the credential using the handshake protocol below:

    <website address>/user-embed/p/<project ID>/conv/<conversation ID>?org_id=<organization ID>&parent_origin=<encoded parent page origin>

Creating a conversation does not send a question automatically. When switching conversations, update the iframe address and handshake again. This entry opens only the user's own conversations; administrators cannot use it to view other people's conversations.

Workspace

<website address>/workspace-embed?org_id=<organization ID>&parent_origin=<encoded parent page origin>&project_id=<initial project ID>
  • project_id is optional; without it, the user's accessible projects are listed.
  • Users use conversations, agents, data sources, skills, project settings, and other features with their existing permissions and can switch projects within the organization; organization switching and system administration are not available.
  • Add &layout=content before the # in the address to hide AskTable's project sidebar and mobile menu button, which suits opening a specific project page directly from your website's menu, for example ...&layout=content#/u/p/<project ID>/data/data-source. Private deployments need 4.2.76 or later.

Handshake protocol

Both modes require org_id and parent_origin. parent_origin is the parent page's location.origin (protocol, host, and non-default port, without path or trailing slash), encoded with URLSearchParams.

Register the message listener before setting the iframe address. The example below is for Workspace; for Chat, use the Chat address, change mode to chat, and also check the project ID and conversation ID in messages.

<iframe id="asktable" title="AskTable" style="width:100%;height:700px;border:0"></iframe>
const webBase = 'https://asktable.example.com'; // may include a deployment subpath, no trailing slash
const askTableOrigin = new URL(webBase).origin;
const orgId = 'your organization ID';
const projectId = 'your project ID';
const frame = document.getElementById('asktable');
let channelId;
let generation = 0;
let closing = false;

window.addEventListener('message', async (event) => {
  if (event.origin !== askTableOrigin || event.source !== frame.contentWindow) return;
  const m = event.data;
  if (!m || m.mode !== 'workspace' || m.org_id !== orgId) return;
  if (m.type === 'asktable.ready' && !closing) {
    channelId = m.channel_id;
    const current = ++generation;
    try {
      // Implemented by your app: get the current user's AskTable user credential.
      const token = await getCurrentAskTableUserToken();
      if (closing || current !== generation) return;
      frame.contentWindow.postMessage({
        type: 'asktable.authenticate', channel_id: channelId, token
      }, askTableOrigin);
    } catch (error) {
      if (!closing && current === generation) showIntegrationError(error);
    }
    return;
  }
  if (!channelId || m.channel_id !== channelId) return;
  if (m.type === 'asktable.loaded') hideLoading();
  if (m.type === 'asktable.error') showIntegrationError(m.code);
  if (m.type === 'asktable.auth_required') {
    // Return to sign-in; reload the iframe after a successful sign-in, with limited retries.
    ++generation;
    showSignIn();
  }
  if (m.type === 'asktable.logged_out') {
    ++generation;
    closing = true;
    frame.src = 'about:blank'; // Unload only after sign-out is confirmed.
  }
});

const params = new URLSearchParams({
  org_id: orgId, parent_origin: location.origin, project_id: projectId
});
frame.src = `${webBase}/workspace-embed?${params}`;

function logoutAskTable() {
  closing = true;
  ++generation; // Discard credential requests still in progress.
  if (channelId) frame.contentWindow.postMessage({
    type: 'asktable.logout', channel_id: channelId
  }, askTableOrigin);
}

getCurrentAskTableUserToken, hideLoading, showIntegrationError, and showSignIn are implemented by your app. In production, also add timeout messages for loading, getting credentials, and signing out; before reloading, switching accounts, or switching conversations, invalidate old credential requests. Keep separate handshake state for each iframe.

MessageDirectionMeaning and handling
asktable.readyiframe → parentRecord the new channel_id and send authenticate
asktable.authenticateparent → iframeCarries the current channel and user credential; the target origin must match exactly, not *
asktable.authenticatediframe → parentIdentity confirmed; does not mean the target page is accessible
asktable.loadediframe → parentThe target page's required data is ready; remove the loading overlay
asktable.auth_requirediframe → parentAuthenticate again with a new credential; limit retries and ask the user to sign in again on failure
asktable.erroriframe → parentShow the error or a retry entry; permission errors cannot be fixed by refreshing the credential
asktable.logoutparent → iframeRequest sign-out with the current channel_id
asktable.logged_outiframe → parentCredentials cleared; only then destroy the iframe; also sent when the user signs out inside the iframe

Messages from AskTable all include mode, org_id, and channel_id; Chat messages also include project_id and conversation_id. The parent page must check these fields, the message origin, and the sending window, and handle only messages for the current channel. When the same user renews the credential, it may receive only authenticated again, and drafts in the input box are kept.

Sign-in and sign-out

  • After the identity is verified, the credential is stored in browser storage on AskTable's own domain. In the same browser, the iframe and AskTable pages opened directly share one identity: switching accounts overwrites the original account, and signing out signs out of both. It cannot be used to run several accounts side by side.
  • Closing the iframe does not sign out. Send logout first and unload after receiving logged_out. Signing out clears only the credential in the browser; it does not revoke the credential on the server.
  • Do not put credentials in URLs, write them to logs, or store them in your website's localStorage.
  • Some browsers restrict third-party storage; verify sign-in, refresh, renewal, account switching, and sign-out on the actual domain and target browsers.

Deployment checks

  • EMBED_ORIGINS in the AskTable web container defaults to *, allowing all HTTP/HTTPS parent pages. To restrict it, set a comma-separated list of exact origins; an empty string disables the handshake. Allowing an origin grants no user permissions.
  • Reverse proxies or CDNs must allow /workspace-embed and /user-embed/ to be embedded; check X-Frame-Options and CSP frame-ancestors. Your website's CSP frame-src must also allow AskTable.
  • HTTPS pages cannot embed HTTP pages. If you set sandbox on the iframe, include at least allow-scripts allow-same-origin, and allow downloads as needed.
  • When credentials are passed only through postMessage, you do not need to open API CORS for your website. If your website calls the AskTable API directly, configure CORS separately. When proxying streaming replies, disable buffering and allow long connections.

Upgrading from the earlier Chat embedding

Platforms that integrated Chat embedding before 4.2.66 must, after upgrading to 4.2.66 or later: add org_id to the address; add mode=chat and org_id to message checks; and wait for logged_out before closing the window when signing out. The AskTable frontend and server must be upgraded together.

Acceptance

Verify on the actual domain: access without permission is rejected; only the user's own conversations open; project switching works; uploads, downloads, and streaming replies work; sign-in, refresh, renewal, account switching, and sign-out behave as expected.