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

# Embed the app

> Show an app inside your platform, already signed in as the person looking at it.

Your platform shows an app your builders create in an iframe. If the app asks people to sign in, it opens on its own sign-in page inside that frame. To open it already signed in as the end user looking at it, your server mints a one-time sign-in token for them and puts it on the iframe URL. Nothing inside the app changes.

## Deciding whether you need a token

An app's visibility decides whether it asks people to sign in, and so whether you need a token at all. Set it with `public_settings` when you [create the app](/api-reference/create-app).

| `public_settings`      | Shown in the app's settings as | Embedding                                                                    |
| :--------------------- | :----------------------------- | :--------------------------------------------------------------------------- |
| `public_without_login` | **Public (no login)**          | Load the app's address directly. You don't need a token.                     |
| `public_with_login`    | **Public (login required)**    | Mint a token for each end user.                                              |
| `private_with_login`   | **Private**                    | Mint a token for each end user. Provisioning them is what gives them access. |

Without sign-in, the app can't tell who's looking at it, so anything that belongs to one person, such as their own saved data, doesn't work. Learn more about [app visibility](/Setting-up-your-app/Managing-access#setting-your-app-visibility).

## Signing the end user in

<Tip>
  **Before you begin:** Create a [workspace API key](/Enterprise/workspace-secrets) in your enterprise workspace with the **Provision app users** and **Mint embed sign-in tokens** permissions. Set **App access** to **All current and future apps**, since your builders keep creating new ones. Send it from your server as `api_key: <key>`, together with `X-Active-Workspace-Id: <workspace id>`.
</Tip>

<Steps>
  <Step title="Provision the end user">
    Send `POST /api/apps/{app_id}/users/provisions` with the end user's email and one of the app's roles:

    ```json theme={null}
    { "email": "dana@example.com", "role": "user" }
    ```

    This gives them access to the app. It's idempotent, so you can call it before every mint. The response's `status` is `created` the first time and `exists` after that.

    Use the email your platform signed the end user in with. Never take it from the browser, or anyone could open an app as anyone else.
  </Step>

  <Step title="Mint a sign-in token">
    Send `POST /api/apps/{app_id}/embed-tokens` with the same email, and the version of the app you want to show:

    ```json theme={null}
    { "email": "dana@example.com", "target": "latest_preview" }
    ```

    | `target`         | What it shows                                                              |
    | :--------------- | :------------------------------------------------------------------------- |
    | `live_site`      | The published app. This is the default.                                    |
    | `latest_preview` | The latest built version, including changes you haven't published.         |
    | `live_preview`   | The app's running sandbox, which shows each change while the agent builds. |

    The response carries `embed_url`, the address of that version with the token already on it, and `expires_in`, which is 60 seconds.
  </Step>

  <Step title="Load the URL in your iframe">
    Set the iframe's `src` to `embed_url`, and the app opens signed in as the end user. A token works only once, so mint a new one each time you load the frame.
  </Step>
</Steps>

## Choosing which version to show

Match `target` to what the end user should see:

* **An app you've published:** Use `live_site`.
* **An app you haven't published:** Use `latest_preview`, which also shows builders their changes as soon as a build finishes.
* **The builder's preview while a build runs:** Use `live_preview`.

## Errors

Minting returns errors as `{"error": {"code", "message", "details"}}`.

| Status | `error.code`       | What it means                                                                                                                                                          |
| :----- | :----------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | `app_not_deployed` | You asked for `live_site`, and the app isn't published.                                                                                                                |
| `400`  | `app_has_no_slug`  | The app doesn't have an address yet.                                                                                                                                   |
| `403`  | `privileged_user`  | The email belongs to the app's owner, an editor, or a service account, including the account your integration authenticates as. Sign-in tokens are for end users only. |
| `404`  | `unknown_user`     | The email isn't provisioned for this app.                                                                                                                              |

The reference integration does all of this in [`embedSession.ts`](https://github.com/base44/base44-platform-starter/blob/main/src/lib/embedSession.ts).

## See also

* [The build turn](/developers/white-label/the-build-turn): Create, preview, and publish the app you're embedding
* [Tenancy and credentials](/developers/white-label/tenancy-and-credentials): The account that owns your builders' apps, and the token that creates them
* [Workspace secrets](/Enterprise/workspace-secrets): Create and manage the workspace API key this page uses
