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

# Embed the partner portal

> Authorize a domain, create a portal-session key, and render the authenticated partner portal inside your own product.

Embedding the portal lets partners get the full Introw experience without leaving your app, which is the surest way to drive adoption. This guide walks the whole three-step embed setup: authorize the domains that may load the portal, create an API key scoped to portal sessions, and use the code samples to create an authenticated session and render the portal in an iframe. By the end, a logged-in user lands straight in the portal with no second sign-in.

## What you'll achieve

The partner portal embedded inside your product, loaded in an authenticated iframe so a user who is already signed in to your app opens directly into their portal, with no extra login. Only the domains you authorize can load it, and the session is minted server-side so your secret never reaches the browser.

## Before you start

<Steps>
  <Step title="Confirm embed is on your plan">
    Embedding the portal is a paid add-on and must be enabled on your plan.
  </Step>

  <Step title="Have the Integrations permission">
    You need the Integrations permission to manage the allowed domains.
  </Step>

  <Step title="Know your embedding domains">
    Gather every domain where your product runs (including subdomains) and have a backend you can run server-side code from.
  </Step>
</Steps>

## Watch it

<Tabs>
  <Tab title="Video">
    <video controls playsInline preload="none" poster="https://assets.introw.io/docs/features/developer/embed/guides/embed-the-partner-portal/steps/01.png?v=1783353180" className="w-full rounded-xl" src="https://assets.introw.io/docs/features/developer/embed/guides/embed-the-partner-portal/video.webm?v=1783353180#t=2.5" />
  </Tab>

  <Tab title="Click through">
    <iframe className="w-full rounded-xl" style={{ width: "100%", aspectRatio: "16 / 11", border: 0, backgroundColor: "#FAFAFA" }} src="https://assets.introw.io/docs/features/developer/embed/guides/embed-the-partner-portal/walkthrough.html?v=1783353180" />
  </Tab>
</Tabs>

## Steps

<Steps>
  <Step title="Open the embed setup">
    Go to [Embed](https://app.introw.io/settings/developers/embed) under Developers and select **Configure** to open the embed setup. It walks through the three things needed to embed the portal: allowed domains, a portal-session key, and the integration code.

    <Frame>
      <img src="https://assets.introw.io/docs/features/developer/embed/guides/embed-the-partner-portal/steps/02.png?v=1783353180" alt="Open the embed setup" />
    </Frame>
  </Step>

  <Step title="Allow the domains that can embed the portal">
    In **Allow your domains to embed Introw**, add each domain where your product runs (for example `app.yourcompany.com`) and select **Add domain**. The portal only loads inside an iframe on these domains, so anything not on the list is blocked, which is what stops other sites from framing your portal.

    * Add every domain and subdomain your product is served from; a domain that is missing here will show a blank or blocked frame.
    * Remove a domain from its row when it no longer needs access, so the allow-list stays tight.

    <Frame>
      <img src="https://assets.introw.io/docs/features/developer/embed/guides/embed-the-partner-portal/steps/03.png?v=1783353180" alt="Allow the domains that can embed the portal" />
    </Frame>
  </Step>

  <Step title="Create a portal-session API key">
    Create a secret API key with the **Portal sessions** write permission. Your backend uses this key to mint authenticated portal session links (the next step), so it must stay server-side and never be exposed in the browser. Follow [Create and manage API keys](/features/developer/api/guides/create-and-manage-api-keys), granting only the portal sessions scope, and copy the secret when it is shown.

    <Frame>
      <img src="https://assets.introw.io/docs/features/developer/embed/guides/embed-the-partner-portal/steps/04.png?v=1783353180" alt="Create a portal-session API key" />
    </Frame>
  </Step>

  <Step title="Integrate the code into your product">
    From your backend, create an authenticated session for the signed-in user by sending their email and your key to the session endpoint, then render the returned URL in an iframe. Pick the sample that matches your stack from the embed setup and drop it in.

    * **Session call** - send a `POST` to `https://api.introw.io/api/v1/auth/session` with the `x-api-key` header set to your portal-session key and a JSON body of `{ "email": "partner@example.com" }`. The response contains a `url` for that user's portal session.
    * **Keep the key on the server** - in browser frameworks, call the endpoint from your own backend route and proxy the result to the client; the key must never ship to the browser. In Next.js, set `INTROW_API_KEY` in your server environment variables.
    * **Render** - load the returned `url` in an `<iframe>` sized to your layout.

    <CodeGroup>
      ```jsx Next.js theme={"theme":{"light":"github-light","dark":"github-dark"}}
      export default async function Home() {
        const request = await fetch('https://api.introw.io/api/v1/auth/session', {
          body: JSON.stringify({ email: 'email@partner.com' }),
          headers: {
            'Content-Type': 'application/json',
            'x-api-key': process.env.INTROW_API_KEY,
          },
          method: 'POST',
        });
        const result = await request.json();
        return (
          <iframe src={result.url} className="h-full w-full" />
        );
      }
      ```

      ```jsx React theme={"theme":{"light":"github-light","dark":"github-dark"}}
      export default function IntrowEmbed() {
        const [iframeUrl, setIframeUrl] = useState('');

        useEffect(() => {
          fetch('/api/introw-session', {
            body: JSON.stringify({ email: 'email@partner.com' }),
            headers: { 'Content-Type': 'application/json' },
            method: 'POST',
          })
            .then(request => request.json())
            .then(result => setIframeUrl(result.url));
        }, []);

        if (!iframeUrl) return null;
        return <iframe src={iframeUrl} className="h-full w-full" />;
      }
      ```

      ```html Vanilla JS theme={"theme":{"light":"github-light","dark":"github-dark"}}
      <!-- Add this to your HTML -->
      <div id="introw-embed"></div>

      <script>
      // This browser code calls your backend /api/introw-session endpoint.
      // Keep INTROW_API_KEY on the server and proxy the session request from there.
      async function initIntrowEmbed() {
        const request = await fetch('/api/introw-session', {
          body: JSON.stringify({ email: 'email@partner.com' }),
          headers: { 'Content-Type': 'application/json' },
          method: 'POST',
        });
        const result = await request.json();

        const iframe = document.createElement('iframe');
        iframe.src = result.url;
        iframe.style.width = '100%';
        iframe.style.height = '100%';
        iframe.style.border = 'none';

        document.getElementById('introw-embed').appendChild(iframe);
      }

      initIntrowEmbed();
      </script>
      ```

      ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
      curl -X POST \
        'https://api.introw.io/api/v1/auth/session' \
        -H 'x-api-key: YOUR_INTROW_API_KEY' \
        -H 'Content-Type: application/json' \
        -d '{"email":"email@partner.com"}'
      ```
    </CodeGroup>
  </Step>
</Steps>

## Verify it worked

A logged-in user opens your product and lands directly in the embedded portal with no second sign-in, on a domain you authorized. The session call returns a `url`, and the iframe renders the portal. On a domain that is not on the allow-list, the frame is blocked, which confirms the allow-list is doing its job.

## Related

<CardGroup cols={2}>
  <Card title="Create and manage API keys" icon="key" href="/features/developer/api/guides/create-and-manage-api-keys">
    Create the portal sessions key this flow needs.
  </Card>

  <Card title="Embed Introw in your CRM" icon="window-maximize" href="./embed-introw-in-your-crm">
    Meet partners inside HubSpot and Salesforce instead.
  </Card>

  <Card title="Implementation reference" icon="screwdriver-wrench" href="../technical">
    Embed settings, limits, and troubleshooting.
  </Card>

  <Card title="Embed overview" icon="code" href="/general/embed-overview">
    The session endpoint and iframe pattern.
  </Card>
</CardGroup>
