> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ubik-agent.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Guide: Integrating UBIK with an iframe

> Learn how to securely embed a UBIK tool's UI directly into your web application for a seamless user experience.

Embedding UBIK tools into your own application provides a powerful way to extend your product's capabilities. This guide will walk you through the process of securely embedding a tool using an `<iframe>`.

<Steps>
  <Step title="Configure Allowed Origins">
    To prevent unauthorized domains from embedding your tools, you must first configure a list of **Allowed Origins** for your API key. This is a critical security step. An "origin" is the combination of a protocol, domain, and port (e.g., `https://yourapp.com`).

    You can set the allowed origins for your API keys in the user settings page on the UBIK dashboard.

    <Card title="Go to API Key Settings" icon="key" href="https://app.ubik-agent.com/user/security" />

    <Note>
      For local development, you can add origins like `http://localhost:3000`. For production, ensure you only add the domains where your application is hosted.
    </Note>
  </Step>

  <Step title="Fetch Embedding Information">
    Before you can render the `<iframe>`, your application's frontend needs to fetch the embedding details from the UBIK API. This is done by making a `GET` request to the `/tools/{tool_id}/embed-info` endpoint.

    This endpoint provides two crucial pieces of information:

    1. **Tool Details**: The schema, name, description, etc.
    2. **Access Token**: A short-lived JSON Web Token (JWT) that the embedded `<iframe>` will use to authenticate itself.

    <CodeGroup title="GET /tools/{tool_id}/embed-info">
      ```bash cURL theme={null}
      curl -X GET "https://app.ubik-agent.com/api/v1/tools/YOUR_TOOL_ID/embed-info" \
           -H "X-API-KEY: YOUR_API_KEY"
      ```

      ```python Python (Server-Side) theme={null}
      import requests

      api_key = "YOUR_API_KEY"
      tool_id = "YOUR_TOOL_ID"

      headers = {"X-API-KEY": api_key}

      # This call would typically be made from your server, which then passes
      # the embed info to your frontend client.
      response = requests.get(
          f"https://app.ubik-agent.com/api/v1/tools/{tool_id}/embed-info",
          headers=headers
      )

      if response.status_code == 200:
          embed_info = response.json()
          print(embed_info)
          # Pass this info to your frontend
      else:
          print(f"Error: {response.status_code}", response.text)
      ```

      ```javascript JavaScript (Client-Side) theme={null}
      // This function would typically call an endpoint on YOUR server, 
      // which then makes the secure call to the UBIK API with your secret API key.

      async function fetchEmbedInfoFromServer(toolId) {
        try {
          // Example: an endpoint on your own backend
          const response = await fetch(`/api/get-tool-embed-info?toolId=${toolId}`);
          if (!response.ok) {
            throw new Error(`HTTP error: ${response.status}`);
          }
          const embedInfo = await response.json();
          console.log(embedInfo);
          // Use this data to render the iframe
          return embedInfo;
        } catch (error) {
          console.error('Error fetching embed info:', error);
        }
      }
      ```
    </CodeGroup>

    <Tip icon="shield-check">
      **Security Best Practice**: Your secret UBIK API key should never be exposed in your frontend application. The call to `/embed-info` should be made from your backend server.
    </Tip>

    ### Multi-Tenancy & User Isolation

    If your application serves multiple users, you likely want to ensure that one user cannot see another's data within the embedded tool.

    You can achieve this by passing the `external_user_id` query parameter to the `/embed-info` endpoint.

    ```bash cURL theme={null}
    curl -X GET "https://app.ubik-agent.com/api/v1/tools/YOUR_TOOL_ID/embed-info?external_user_id=user_456" \
         -H "X-API-KEY: YOUR_API_KEY"
    ```

    The returned `access_token` will be automatically scoped to `user_456`. When you pass this token to the iframe, all actions (like saving state or accessing files) will be strictly isolated to that user.

    <Note>
      Alternatively, you can generate user-scoped tokens using the generic `/auth/token` endpoint. See the [Authentication & Security Guide](/en/guides/authentication) for details.
    </Note>

    <Warning>
      **Important**: If you do not provide an `external_user_id` when generating the token, the embedded tool will have **full access** to all resources (documents, previous executions) associated with your API Key. This effectively grants "Admin" privileges within the iframe and should never be used for end-user facing integrations.
    </Warning>
  </Step>

  <Step title="Render the iframe">
    Once your frontend has the embedding information, you can construct the `<iframe>` URL and render it. The `access_token` from the `embed-info` endpoint must be passed as a `jwt` query parameter to the `iframe`'s source URL.

    Here is a simplified example using React:

    ```jsx React Example theme={null}
    import React, { useState, useEffect } from 'react';

    const EmbeddedTool = ({ toolId }) => {
      const [embedInfo, setEmbedInfo] = useState(null);

      useEffect(() => {
        // In a real app, this would fetch from your backend
        const fetchEmbedInfo = async () => {
          try {
            const response = await fetch(`/api/get-tool-embed-info?toolId=${toolId}`);
            const data = await response.json();
            setEmbedInfo(data);
          } catch (error) {
            console.error("Failed to fetch embed info:", error);
          }
        };

        fetchEmbedInfo();
      }, [toolId]);

      if (!embedInfo) {
        return <div>Loading Tool...</div>;
      }

      // Append the access token as a query parameter.
      // Note: If you generated a user-scoped token via /auth/token, use that here instead.
      const iframeSrc = `https://app.ubik-agent.com/embed/tools/${embedInfo.id}?jwt=${embedInfo.access_token}`;

      return (
        <iframe
          src={iframeSrc}
          title={embedInfo.name}
          width="100%"
          height="600px"
          frameBorder="0"
        />
      );
    };

    export default EmbeddedTool;
    ```

    <Note>
      **Using a direct API Key:** For scenarios where you prefer not to use the `/embed-info` endpoint (e.g., server-side rendering), you can also authenticate by passing your UBIK API key directly as the `apiKey` query parameter.

      `const iframeSrc = `[https://app.ubik-agent.com/embed/tools/YOUR\_TOOL\_ID?apiKey=YOUR\_API\_KEY\`;\`](https://app.ubik-agent.com/embed/tools/YOUR_TOOL_ID?apiKey=YOUR_API_KEY`;`)

      However, for client-side applications, using the short-lived `access_token` is strongly recommended to avoid exposing your secret API key.
    </Note>
  </Step>

  <Step title="Customize the Embedded Tool">
    You can customize the appearance and behavior of the embedded tool by adding query parameters to the `<iframe>` source URL.

    Here is a list of available parameters:

    * **`jwt`** (string): A short-lived JSON Web Token. Use the one from `/tools/{tool_id}/embed-info` (optionally with `external_user_id` for isolation).
    * **`apiKey`** (string): Your UBIK API key. This can be used for authentication instead of a JWT, but it is less secure for client-side applications as it may expose your secret key.
    * **`theme`** ('light' | 'dark'): Sets the default color theme for the tool's UI. If not provided, it defaults to the user's system preference.
    * **`showThemeToggle`** (boolean): If set to `true`, a theme toggle switch will be displayed in the tool's header, allowing users to switch between light and dark mode.
    * **`showLangToggle`** (boolean): If set to `true`, a language selector will be displayed, allowing users to change the display language.

    Example URL with customization:

    ```
    https://app.ubik-agent.com/embed/tools/YOUR_TOOL_ID?jwt=YOUR_JWT&theme=dark&showThemeToggle=true
    ```
  </Step>

  <Step title="Embedding a Specific Execution">
    In addition to embedding the tool input form, you can also embed a specific **existing execution**. This is ideal for sharing results with users or allowing them to monitor a long-running task that was initiated via the API.

    The process is identical to embedding a tool, but you use a different URL path.

    **URL Format:**
    `https://app.ubik-agent.com/embed/execution/YOUR_EXECUTION_ID?jwt=YOUR_JWT`

    **Or with an API Key (Server-side rendering only):**
    `https://app.ubik-agent.com/embed/execution/YOUR_EXECUTION_ID?apiKey=YOUR_API_KEY`

    **Use Cases:**

    * **Monitoring:** Redirect a user to this view after starting a task via the API.
    * **Sharing:** Allow users to view the results of a completed task.

    The embedded view will automatically handle:

    * Connecting to the real-time event stream.
    * Displaying progress and intermediate steps.
    * Rendering the final results (text, images, files) when complete.
  </Step>

  <Step title="Handling Events (Advanced)">
    The embedded iframe handles all real-time events, state management, and user interactions internally. You do not need to write any additional code to handle tool progress or results.

    However, if you need to build a completely custom interface that reacts to tool events programmatically (e.g., for deep integration into your own UI framework), you should use the API directly instead of the iframe.

    The main events to monitor are:

    * `tool_update`: General progress.
    * `tool_partial_update`: Content streaming.
    * `tool_input_required`: Request for user interaction.
    * `tool_end` (or `final_result`): Execution completion with results.
    * `error`: Execution error.

    For details on consuming the raw event stream, please refer to the **[Getting Real-Time Results with SSE](/en/guides/streaming-results)** guide.
  </Step>
</Steps>

By following these steps, you can securely embed UBIK's powerful tools directly into your application, creating a seamless and integrated experience for your users.
