Embed Retool apps

Learn how to use Retool Embed to share apps with external users.

🚧

Retool Embed is in beta and only available to users running Self-hosted Retool. You can book a demo with our team to learn more about self-hosting Retool.

Retool Embed allows you to embed apps for external users in a secure, managed way. Not much changes in how you build your apps, but you need to complete a few steps to embed your apps for external use:

  1. Generate an access token so you can create sessions for embedding apps.
  2. Create permission groups for your users so you can give them access to apps.
  3. Create an embed URL to use when embedding Retool apps into your parent app.
  4. Use the embed URL to display the app.

Prerequisites

To use Retool Embed, you need to:

  • Self-host Retool with v2.108.5 or later.
  • Turn Prevent Query Spoofing on.
  • Host Retool on the same top-level domain as the parent application.
  • Use HTTPS when generating embed URLs.
  • Have already built a Retool app to embed.

If you haven't reviewed the Retool Embed overview yet, you might want to read through it before continuing. It provides some additional context about Retool Embed and its uses.

1. Generate an access token

To embed apps, you need to create an access token with the Embed scope. This token allows you to create sessions for embedding Retool apps.

To generate the token:

  1. Navigate to the Retool API page at /settings/api.
  2. Click Create new.
  3. Enter a name and description, and make sure to select the App: Embed scope.

Creating a token with the Embed scope

Save this token securely in your backend. It's used later to generate embed URLs.

2. Create permission groups for your users

Permission groups determine the apps users can access. Depending on your use case, you might need to create more than one permission group.

To create a permission group:

  1. Navigate to the Permission Groups page at /settings/permissions.
  2. Click Create new in the top right and complete the form to create a group.
  3. On the Members tab, click + Add new members to add users.
  4. On the Apps tab, enable Use access to the apps you want users to have access to.

Giving users access to apps

Make sure to note down the group IDs you want to give access to. You can find a group's ID by hovering over the group, clicking the ••• menu, and then selecting Copy group ID.

Copying the group ID

3. Create an embed URL

The embed URL is a single-use link to a Retool app for an authenticated user. Your backend sends a POST request to /api/embed-url/external-user with a few parameters, and Retool returns the URL. This URL is then used by your frontend to display the app.

POST request parameters

The table below outlines the parameters you can send, and whether they're required.

ParameterRequiredDescription
landingPageUuidYesA string to specify the page in the Retool app to render.
groupIdsYesAn array of strings specifying the Retool group IDs to allow.
sessionDurationMinutesNoThe session token's duration, in minutes. If unset, defaults to 600. Values from 10 to 600 are accepted.
externalIdentifierYesA unique identifier for the external user.
userInfoNoUser profile information. Can contain string fields for email, first_name, and last_name.
metadataNoAdditional metadata. Accepts strings, int64, and booleans. Can be at most 1KB of stringified JSON.
environmentNoA string to specify an environment for the app to run in.
branchNoA string to specify a branch to be displayed. You can't display both releaseVersion and branch.
releaseVersionNoA string to specify a release to be displayed. Defaults to latest but you can pass version numbers too (e.g.,1.0.0). You can't display both releaseVersion and branch.

📘

You can find the landingPageUuid by opening the app and using the Command Palette (opened with Ctrl k) to select Copy app UUID. You can also copy the set of alphanumeric values in the app's URL (e.g., https://your_domain.retool.com/apps/**233861a-14-11d-a4-af6f2330**/your_app).

POST request code example

Below is sample code that accepts a request from the client, builds and sends the POST request to /api/embed-url/external-user, receives the embed URL, and then returns the URL to the client.

@app.route('/embedUrl', methods=['POST'])
def embed_url():
  data = request.get_json()
  app_uuid = app_name_to_uuid[data['retoolAppName']]
  token, first_name, last_name, email = jwt.decode(data['userJwt'], secret_key)

  headers = {
    // The RETOOL_API_KEY is the token generated in the first step
    'Authorization': f"Bearer {os.environ['RETOOL_API_KEY']}",
    'Content-type': 'application/json',
  }
  body = {
    'landingPageUuid': app_uuid,
    'groupIds': [12, 13],
    'externalIdentifier': token,
    'userInfo': {
      'first_name': first_name,
      'last_name': last_name,
      'email': email,
    },
    'metadata': {
      'storeId': 5
    }
  }

  options = {
    'method': 'POST',
    'headers': headers,
    'body': json.dumps(body),
  }

  resp = requests.post(f"https://{os.environ['RETOOL_URL']}/api/embed-url/external-user", **options)
  if resp.ok:
    return resp.json()
  else:
    # Handle error
    pass

📘

If you need to make sure users can only see data specific to them, see the Control access and app behavior with metadata section.

4. Use the embed URL to display the app

On your frontend, use the Retool React component to render the embed URL. Below is a sample request your frontend would make to your backend.

const RetoolWrapper = ({ retoolAppName, userJwt }) => {
  const [retoolEmbedUrl, setRetoolEmbedUrl] = useState("");

  useEffect(() => {
    const options = {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ userJwt, retoolAppName }),
    };
    fetch("/api/embedUrl", options)
      .then((res) => res.json())
      .then((data) => {
        setRetoolEmbedUrl(data.embedUrl);
      });
  }, [retoolAppName]);

  return (
    retoolEmbedUrl && (
      <Container maxWidth={false} disableGutters>
        <Retool url={retoolEmbedUrl} />
      </Container>
    )
  );
};

Control data access and app behavior

There are a few ways to manage data access and control app behavior beyond permission groups. If permission groups don't provide the customization you need, try using metadata or React to interact with the parent application.

Control access and app behavior with metadata

You can pass information in the metadata object to dynamically control the data users see and behavior within an application. These variables are added to the current_user.metadata object when the embed URL is generated.

For example, with the set of metadata below, you could use the storeId to filter sales metrics for a specific store, or show a download button to users with canExportData enabled.

const options = {
  method: "post",
  headers: {
    Authorization: `Bearer ${process.env.RETOOL_API_KEY}`,
    "content-type": "application/json",
  },
  body: JSON.stringify({
    landingPageUuid: LANDING_PAGE_UUID,
    externalIdentifier: token,
    groupIds: [12, 13],
    userInfo: {
      first_name,
      last_name,
      email,
    },
    metadata: {
      storeId: 51,
      isAdmin: true,
      canExportData: true,
    },
  }),
};

Because current_user.metadata values are populated only when the embed URL is generated, you don't have access to them while you build your app. However, you can create a transformer that returns mock values that you can use while working on your app. After building your app, you can then replace each reference to the transformer with the values passed in the metadata object. These values are injected into the current_user.metadata object when the URL is generated.

Interact with the parent application

You can interact with the parent application using React. Depending on your use case, you can listen for updates from Retool, or post information directly to the parent application.

Listen for updates from Retool

With the react-retool library, you can set up hooks that listen to state updates within the parent application. To do so, pass in a data object as a prop into the <Retool> component.

const RetoolWrapper = ({ isAdmin }) => (
  <Retool
    url={<your_embed_url>}
    data={isAdmin}
  />
)

Within the embedded Retool application, you can set up a Parent Window Query whose selector is a key within the data object:

Using a Parent Window Query

This application allows the user to export the report if isAdmin is true on the parent application. When the parent application changes, the Parent Window Query reruns and updates its value.

Export to S3 button is disabled when isAdmin is false

Post information to the parent application

You can write JavaScript queries within Retool that use the postMessage browser API to pass data to the parent application or invoke callback functions.

For example, the code below triggers a navigation change in the parent application from the embedded Retool app.

parent.postMessage("home", "https://retool.example.com");

You can also use the react-retool library to pass a function into the onData property. This function accepts data passed in from the JavaScript query called within the Retool app. For example, React code that sets the active tab in the app might look like this:

<Retool onData={(tab) => setActiveTab(tab)} />

View usage

Activity is logged for users that have access to your embedded apps. These users have the External user type, and you can view them on the Users page. Select a user to view which apps they've accessed and session metadata associated with them.