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

# Embedded portal

> Embed the Introw partner portal inside your own product with pre-authenticated sessions.

Embed the Introw partner portal directly inside your product. Partners get a seamless, single-login experience — no separate Introw login screen, fully branded, served inside an `<iframe>`. Your backend mints a short-lived, pre-authenticated portal URL with the [Create a portal session](/api-reference/auth/create-a-portal-session) endpoint and you render it.

## Why embed

* **Seamless experience** — partners stay in your product instead of context-switching to another tool.
* **One login** — the session URL signs the partner in automatically, so they never see an Introw login screen.
* **Quick & easy implementation** — a single backend call plus an iframe.
* **Fully branded** — the portal renders inside your UI with your domain and styling.

## How it works

1. Your backend calls `POST /api/v1/auth/session` with the partner visitor's email and your secret API key.
2. Introw returns a single-use, short-lived `url` that carries a sign-in token.
3. You render that `url` in an `<iframe>`. The partner is logged in automatically.

The visitor must already have portal access in the API key's organisation. Generate a fresh URL per visitor session — the token is short-lived and single-use.

## Setup

### 1. Allow-list your embedding domains

In Introw, go to **Settings → Developers → Embed** and add every domain where you embed the portal. Only allow-listed domains can load Introw in an iframe.

### 2. Create a secret API key

Create an API key with the `portal-sessions:write` scope under **Settings → Developers → API keys**. This key authenticates the backend request in the next step.

<Warning>
  Keep this key on your server. Never call `/api/v1/auth/session` directly from the browser — it would expose your secret API key.
</Warning>

### 3. Mint a session from your backend

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
curl -X POST "https://api.introw.io/api/v1/auth/session" \
  -H "x-api-key: $INTROW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "email": "partner.user@acme.example" }'
```

Response:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "url": "https://partners.acme.example/?token=eyJhbGciOiJIUzI1NiJ9.example"
}
```

Pass `roomId` to deep-link the partner into a specific room after authentication:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{ "email": "partner.user@acme.example", "roomId": "room_01HVK6Y8Z8Q7J8J8J8J8J8J8J8" }
```

### 4. Render the portal

The recommended pattern is to proxy the session request through your own backend route, then load the returned URL in an iframe. For example, in Next.js:

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

For React, Vanilla JS, and other stacks, keep `INTROW_API_KEY` on the server and proxy the call from a backend route (for example `/api/introw-session`) that the browser fetches.

## Authentication

Create an API key with the `portal-sessions:write` scope. See [Authentication](/general/authentication) for key creation, rotation, and request signing.

## API reference

<CardGroup cols={1}>
  <Card title="Create a portal session" icon="window-restore" href="/api-reference/auth/create-a-portal-session">
    POST /api/v1/auth/session
  </Card>
</CardGroup>
