# Follow the step by step instructions to create a resource and register a server
npx retool-cli rpc
```

If you already have a project, you can register a server with Retool's SDK. This is the recommended way to set up Retool RPC for production.

Create an RPC resource

Sign in to your Retool organization and [create a Retool RPC resource](https://login.retool.com/auth/login?source=docs&redirectOnLogin=resources/new/retoolSdk).

After creating the resource, Retool provides instructions and a code snippet. In the code snippet, `resourceId` is already populated for you.

Generate an access token

Create an access token with the RPC scope by navigating to your [access tokens page](https://login.retool.com/auth/login?source=docs&redirectOnLogin=settings/api). Save this token somewhere safe since you'll need it to register your server.

Register a server

Copy the code snippet from the resource form instructions into a file that can access your codebase. Be sure to populate all fields (e.g., replace the `apiToken` with the token you generated in the previous step) and install relevant dependencies.

:::warning
If you're a cloud customer and your server is running in a private network, you may need to allow outbound traffic to [Retool IP addresses](https://docs.retool.com/data-sources/quickstarts/resources).
:::

Run the file to register your server with Retool. This file serves as the entry point to your codebase and must be running for Retool to communicate with your code.

## 2. Define server-side functions

After registering your server with Retool, you can interact with your codebase. You need to define functions through your registered server, fill in the implementation, and then call the function from Retool apps.

:::warning
Be sure to restart your server to pick up any changes to your registered functions.
:::

Retool RPC allows you to customize functions with any number of arguments. Currently supported argument types are: `string`, `number`, `boolean`, `json`, and `array`. You can also specify whether an argument is required or optional.

```js
// server.js

rpc.register({
  name: "randomFunction",
  arguments: {
    stringInput: {
      type: "string",
      description: "A required string input",
      required: true,
    },
    numberInput: {
      type: "number",
      description: "A required number input",
      required: true,
    },
    booleanInput: { type: "boolean", description: "An optional boolean input" },
    jsonInput: { type: "json", description: "An optional json input" },
    stringArrayInput: {
      type: "string",
      array: true,
      description: "An optional string array input",
    },
    jsonArrayInput: {
      type: "json",
      array: true,
      description: "An optional json array input",
    },
  },
  implementation: async (args, context) => {
    console.log(args.stringInput);
    console.log(context.userEmail);
    // Use parts of your codebase here
  },
});
```

The `args` parameter contains the arguments passed in from Retool, and the `context` parameter contains information about the user that called the function. Fill in the implementation of the function. Since this server connects to your codebase, you can use your existing infrastructure (ORM frameworks, helper functions, logging, testing, CI/CD, etc.) to enhance the developer experience.

## 3. Call server-side functions from Retool

After registering server-side functions, you can call them from Retool apps like [any other resource](https://docs.retool.com/data-sources/quickstarts/resources). Search for the RPC resource you created and select the function you want to call. Retool automatically generates a form for you to fill in the arguments.

Enter the arguments and click **Run** to execute the function. Retool automatically checks the argument passed and displays an error if the types don't match or required fields are missing.

## 4. Configure function permissions

You can configure permissions to control access to exposed functions within your organization. Unlike private APIs that require you to build your own authentication middleware, Retool RPC makes it easy to enforce user or [group-level](https://docs.retool.com/permissions/tutorial) access to functions.

```js
rpc.register({
  name: "randomFunctionWithPermissions",
  arguments: {
    stringInput: { type: "string", description: "A string input" },
  },
  permissions: {
    userEmails: ["hello@world.com"],
    groupNames: ["Hello world group"],
  },
  implementation: async (args, context) => {
    return "Hello world!";
  },
});
```

By default, all functions are accessible to all users. If a `userEmails` or `groupNames` field is specified, only users with the specified email or in the specified group can call the function. If both are provided, users only need to satisfy one condition.

## 5. Configure schema versioning

Retool RPC supports schema versioning to ensure exposed functions are always up-to-date. If you check `Require explicit version` on the resource form, you must increment the version on every server change. This is to ensure non-conflicting changes if multiple people are testing different schemas with the same resource.

```js
const rpc = new RetoolRPC({
  apiToken: 'API_TOKEN',
  host: 'HOST',
  resourceId: 'RESOURCE_ID',
  version: '0.0.1', // Increment this on every server change e.g., 0.0.1 -> 0.0.2 -> 0.0.3
})
```

If left unchecked, Retool uses the last registered server's schema. This is useful for early development where you want to quickly iterate on your functions.

Retool prompts users to refresh their schema if they are running queries against an outdated schema. This can be done by clicking the refresh button on the **Schema** tab or by refreshing the page.

---

## Retool Storage tutorial

Retool Storage is a Retool-hosted file store. In this guide, you build an app with the following functionality:

- Generate a PDF from a Chart component
- Upload the PDF to Retool Storage
- Send emails using Retool Email with the Retool Storage file attached

To test out the app yourself, you can [download the app as JSON](/img/docs/demos/c4c42327-0331-4f8a-ae70-8df7c0dae761.json) and [import](../../apps/guides/app-management/import-export.mdx) it to your organization. See the [Retool Storage overview](../quickstarts/retool-storage.mdx) to learn about other ways to use Retool Storage.

### 1. Add a Chart component

In the **Apps** tab, click **Create new > App** to create an app. Name the app and then click **Create app**.

To help organize your app, add a Tabbed Container and label the steps **Generate PDF**, **Store PDF**, and **Send email**. Add a Chart component to your app and drag it to the canvas. This app uses sample data, but you can also use your own data to populate the chart.

### 2. Generate a PDF

To generate a PDF from components in your app, you can use Retool's build-in [utility methods](../../queries/reference/libraries/utils.mdx). Create a JavaScript query and enter the following code. Add any additional components you want to include to the `componentsToInclude` array.

```javascript
utils.downloadPage("report.pdf", { componentsToInclude: ["chart1"] });
```

Next, add a Button component to the canvas and update its label to **Generate PDF**. In the Button's Inspector, attach an event handler to trigger your `downloadPage` query.

### 3. Upload a PDF to Retool Storage

You can upload files to Retool Storage in apps using the File Button, File Input, and File Dropzone components. In the **Store PDF** tab of your container, add a File Button component.

Next, add a resource query and set the resource to Retool Storage. Set the **Action type** to **Upload file** and the **File source** to your File Button component. Select **Make file public on upload** to allow the file to be accessed outside of Retool. You can change this later from the **Retool Storage** resource page (`.retool.com/files`).

### 4. List uploaded files

Create another Retool Storage query, rename it to `listFiles`, and set the **Action type** to **Get a list of file metadata**. This retrieves a list of all files uploaded to Retool Storage for your organization, so you may want to filter some files from the list. In this example, the following **Transformer** filters the list of files to only PDFs.

```javascript
return data.filter((file) => file.type === "application/pdf");
```

In the **Send email** tab, add a Select component. Set the **Mode** to **Mapped**, and set its **Data source** to this query. Update its label to **File**.

### 5. Retrieve file contents

Create another Retool Storage query and rename it to `getFileContents`. Set the **Action type** to **Get file contents**, then set the file name to `{{ select1.value }}`. File contents retrieved from [Retool Storage queries](../quickstarts/retool-storage.mdx) are stored in `queryName.data.base64Data`.

Attach an event handler to the Select component to trigger `getFileContents`, so the query retrieves the contents of the selected file.

### 4. Send emails with file attachments

Add an Email component to specify the recipient.

Next, add a resource query using **Retool Email** as the resource. Set the **To** field to `{{ email1.value }}`, and fill in the rest of the fields with your desired content. In **Attachments**, toggle the `fx` option, and set the field to:

```javascript
[{data: {{ getFileContents.data.base64Data }}, name: {{ getFileContents.data.name }}, contentType: 'application/pdf'}]
```

Add a Button component and label it **Send**, and attach an event handler to the button to trigger `sendEmail`.

### 5. Test your app

Enter a test email and click **Send** to test your queries. You can also prevent sending emails to invalid addresses by setting the **Disabled** field of the **Send** button to `{{ !textInput || textInput.validationMessage }}`.

---

## Retool-managed Vectors tutorial

Retool-managed Vectors is a hosted vector database that enables you to store unstructured text from documents and web pages for use with AI models through Retool. Retool abstracts away the complexities of preparing text and automatically generates the required data for AI models to make decisions using your data.

You can include related information from [Retool-managed Vectors](../quickstarts/retool-vectors.mdx) to provide more context. This allows you to instruct AI models to use your own data when making decisions, such as responding to a customer with context from support articles.

The following guide explains how to add text to Retool-managed Vectors and use it with the [Generate text](../../queries/guides/ai/text.mdx#generate-text) AI Action.

:::info Vector contents

Each vector you create can contain either document text or URLs, not both.
:::

## 1. Enable Vectors

import Enable from '/docs/_shared/_enable-vectors.mdx';

## 2. Create a Vector

To get started, navigate to the **Resources** tab in your organization and select **Retool Vectors**. You can create two types of Vectors:

- [Document Vector](../guides/vectors/text.mdx): Store plain text that you enter manually or extract from uploaded PDF documents.
- [URL Vector](../guides/vectors/urls.mdx): Store text fetched from publicly accessible web pages.

The following instructions cover both Vector types. To continue with this guide, create a **URL Vector**.

import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";

To create a Document Vector:

1. Navigate to the **Resources** settings and click **Retool Vectors**.
2. Click **Add Vector**.
3. Specify a name and select **Document**.
4. Click **Create**.

To create a URL Vector:

1. Navigate to the **Resources** settings and click **Retool Vectors**.
2. Click **Add Vector**.
3. Specify a name and select **Site URLs**.
4. Click **Create**.

## 3. Add embeddings

Click **Add document** and select whether to upload a PDF file or add plain text manually. Retool extracts text from PDF documents automatically.

:::info URLs must be publicly accessible
Retool can only crawl URLs that are publicly accessible and linked from other pages that match the base URLs. Pages that can only be accessed directly or require authentication cannot be added.
:::

Click **Add URLs** to add web pages to the Vector then add a base URL to **Links to crawl**. You can specify multiple URLs by clicking **Add link**.

You only need to specify a base URL, such as `https://docs.retool.com`—Retool crawls the URL and fetches text for any pages at this location. You can exclude web pages by providing a base URL in **Link prefix to exclude**—any URLs that match are not crawled.

For the purposes of this guide, set the following:

- **Links to crawl**: `https://docs.retool.com`
- **Link prefix to exclude**: `https://docs.retool.com/changelog`

This instructs Retool-managed Vectors to crawl Retool Docs but exclude changelog content.

## 4. Use Retool-managed Vectors in AI Actions

You can include context from Retool-managed Vectors in apps and workflows using the [Generate text](../../queries/guides/ai/text.mdx#generate-text) and [Generate chat response](../../queries/guides/ai/chat.mdx) AI Actions. This step assumes you have created a URL Vector using `https://docs.retool.com`.

1. Navigate to the **Query Library** tab and click **+ New**.
2. Set **Resource** to **Retool AI**.
3. Select the **Generate text** action.
4. Enter `What is a resource?` as the **Input**.
5. Enable **Use Retool Vectors to provide more context to your query** and select the URL Vector you created.
6. Click **▶︎** to run the query.

Retool automatically includes relevant context to the AI model from the specified Vector.

## Wrap up

You have now created a new vector store using Retool-managed Vectors, added text content, and performed an AI Action with Vector context.

---

## Resources tutorials

import Tutorial from '/docs/_partials/_doctypes/_tutorial.mdx';

:::tip Learn more about data sources and resources

Read the [resources](./tutorials.mdx) quickstart guide to learn more about connecting data sources with your Retool organization.

:::

---

## Autofill forms

You can pass default URL query string and hash parameters to forms, similar to how you pass [parameters to apps](../../apps/guides/app-management/customize-app-urls.mdx#launch-an-app-with-url-query-parameters). Use the [urlparams](../reference/objects/url.mdx) object to populate default values.

For example, if you set a **Quantity** form field's default value to `{{ urlparams.quantity }}`, passing the query string `?quantity=5` in the URL pre-populates the field with `5`.

---

## Manage fields

### Use AI to generate fields

If you use Retool Database, you can use AI to generate a form for your use case. From a blank form, select **Click here to start with AI**, and provide your use case. Fields are then automatically generated, which you can further customize. A table named after your form is created when you publish the form, and contains columns for each input field in your form.

### Add presentation fields

You can add Text, Image, and Divider fields from the **+** button. These can help you organize your form and provide additional context to users. Presentation fields do not affect data written to your database.

### Add custom fields

You can add custom fields to forms connected to Retool Database. When you publish your form, a column is inserted into your database with the settings from the custom field. Custom fields default to use the name of the input component, so you may want to change this name before you publish.

## Hide fields

It can be useful to hide database fields, especially those which have default values set by your database, from your form.

When you hide a field from the sidebar, the field is not passed to the database insert request. You may want to use this to hide `id`, `created_at`, or other auto-generated fields, so your database can handle these inserts.

To hide a field from users, but still include it in the database insert request, use the **Hidden** field in the field settings. You can use this conditionally hide fields based on any criteria. For example, to hide a `custom_name` field when the `status` field is not `'new'`, you could set **Hidden** to `{{ status.value !== 'new' }}`. When the `status` field is not `new`, the `custom_name` field is set to `null`.

## Delete fields

You can delete fields from your form by clicking the delete icon. Non-presentation fields must be hidden before you can delete them.

---

## Configure themes

In the **Settings** tab, you can customize the color, typography, and border radius on your form to match your organization's branding.

---

## Forms how-to guides

import Howto from '/docs/_partials/_doctypes/_howto.mdx';

---

## Retool Forms documentation

Retool Forms enables you to build standalone, customizable forms. Forms are publicly accessible with unique URLs and responses are written to a connected SQL database (Retool Database, MySQL, PostgreSQL, etc.).

:::warning

This section covers only Retool Forms, which are standalone and cannot be embedded in an app. For in-app forms, refer to the [form component guides](../apps/guides/forms-inputs/forms/index.mdx).

:::

---

## The Current User object

:::tip Not available in public forms

`current_user`  is `null` for publicly accessible forms.

:::

## Properties

---

## The Retool Context object

## Properties

---

## The Theme object

## Properties

## Methods

---

## The Url object

## Properties

---

## The Viewport object

## Properties

---

## Retool Forms reference

import Reference from '/docs/_partials/_doctypes/_reference.mdx';

:::tip Get started with forms

Follow the [tutorial](./tutorial/) to build your first form.

:::

---

## Retool Forms tutorial

Use Retool Forms to build standalone, customizable forms whose responses are written to a connected SQL database (MySQL, PostgreSQL, etc.). Forms are publicly accessible from a unique URL.

:::warning

This tutorial covers only Retool Forms, which are standalone and cannot be embedded in an app. To build forms within apps, use a [Form component](../apps/reference/components/containers-forms/index.mdx).

:::

## Requirements

Retool Forms is available on Retool Cloud and self-hosted Retool versions 3.36 and later. 

All users can create and fill out forms. You can build as many forms as you'd like and capture as many responses as your database supports.

To connect forms to an existing database, you must first connect the database as a [resource](../data-sources/quickstarts/resources.mdx) in Retool. To use [Retool Database](../data-sources/tutorials/retool-database.mdx) to store responses on self-hosted Retool, you must first [configure Retool Database](../self-hosted/guides/retool-database.mdx). On cloud-hosted Retool, no additional configuration is required to use Retool Database.

## 1. Create a form

Go to the **Forms** tab and select **Create form**. Name your form and select **Create form**.

## 2. Connect your data

In the **Database** tab, select **Generate from database** to write responses to an existing database, or **Start from scratch** to store responses in Retool Database. From the **Database** tab, you can change the underlying database at any time.

If you create your form from scratch, a new table is automatically generated when you [publish your form](#6-preview-and-publish-your-form). Generated tables are named after your form.

If your database schema changes as you build your form, you can select **...** > **Sync from database** to view and sync schema changes to your form.

## 3. Build your form

You can use the sidebar to reorder your form, and use the drag-and-drop form editor to customize individual fields.

## 4. Connect a workflow

:::info

Triggering Retool workflows from form submissions is currently rolling out for self-hosted Retool.

:::

From the **Workflows** tab, you can trigger a [Retool workflow](../workflows/index.mdx) on successful form submissions. Ensure your workflow has [webhook triggers](../workflows/guides/triggers/webhooks.mdx) enabled. All form fields are passed as workflow parameters.

## 5. Set themes

In the **Settings** tab, you can customize the color, typography, and border radius on your form to match your organization's branding.

## 6. Preview and publish your form

To preview your form before you publish it, select the preview icon in the upper right. To generate a shareable URL for your form, select **Publish** in the upper right. Once published, the form is accessible to any user given the unique URL.

## 7. Use form responses

After you publish and distribute your form, select the **Responses** tab to view form responses. Responses are read-only, but you can click **Clone as Retool app** to copy the data to an app, or **Download** to download the data as a CSV.

---

## Glossary of terms

Definitions of terms you may come across when building software on Retool.

## A

## B

## C

## D

## E

## F

## G

## H

## I

## J

## K

## L

## M

## N

## O

## P

## Q

## R

## S

## T

## U

## V

## W

## X

## Y

## Z

---

## Index

import DocCardList from "@theme/DocCardList";
import VersionCard from "@theme/VersionCard";
import VersionCardList from "@theme/VersionCardList";
import RecentChangelog from "@theme/RecentChangelog";
import ReleasesForLanding from "@site/src/components/ReleasesForLanding";

  Retool Docs
  Build internal software better with AI
  Create apps, agents, and workflows with any LLM, data source, or API. Deploy AI across your business.

  Generate apps with Assist
  Automate work with Agents

## What's new

Updates, changes, and improvements at Retool.

## Latest releases

The latest versions of supported self-hosted Retool releases.

## Explore the platform

Seamlessly connect databases, build with elegant components, and customize with code. Accelerate mundane tasks, freeing up time for the work that matters most.

---

## Mobile app best practices

import Shared from '/docs/_shared/_app-performance-best-practices.mdx';

## Enable cache on page load

If your users will be using your app in an area with low connectivity or or slow connection, consider turning on **Enable Cache page load** in **Settings** > **Mobile Advanced Settings**. This setting allows you to cache the app state on mobile devices to improve performance.

:::note

Enabling this setting may mean that users do not get the most recent version of your app. Users will see a top banner indicating that the app has been updated.

:::

---

## Mobile app biometric verification

Biometric verification enhances the security of your Retool mobile apps by adding an extra layer of identity verification using biometric data. After users log in, they are prompted to verify their identity using biometrics each time they bring the app to the foreground. Biometric verification does not replace your existing login mechanisms.

## Enable biometric verification

Go to **Settings** > **Mobile Advanced Settings** and toggle **Retool Mobile: Enable user verification via biometrics** on.

To allow users to use screen lock credentials (e.g., passcode or pattern) as a fallback to biometrics, select **Retool Mobile: Enable user verification via screen lock credentials**. The device's operating system determines when this fallback is used, and may prompt for the fallback after consecutive failures or if biometrics are unavailable.

You can also enable the **Privacy Screen**, which obscures the app preview when viewed from the mobile device's app switcher.

## Verification behavior

The first time users log in to Retool Mobile apps after enabling biometric verification, they are prompted to set up biometric authentication—e.g., enrolling fingerprints or enabling face recognition. For future logins, when users bring the app to the foreground after logging in, they are prompted to verify their identity using biometrics.

If biometric validation fails after three attempts, users are logged out of the app.

## Security

Retool does not store any biometric data. Biometric validation relies on the security features of the underlying operating system to securely provide and handle biometric data.

---

## Command Palette

import Shared from '/docs/_shared/_command-palette.mdx';

---

## Debug Tools

import Shared from '/docs/_shared/_debug-tools.mdx';

---

## Programming paradigms at Retool

import Shared from '/docs/_shared/_programming-paradigms.mdx';

---

## Push notifications

Retool Cloud and Self-hosted organizations can send push notifications to Retool Mobile users. Push notifications are a built-in feature made available using the Retool Mobile app for iOS and Android.

Retool uses [Amazon SNS](https://aws.amazon.com/sns/) to provide a centralized service for push notifications in Retool Mobile. This makes it possible for Retool organizations to send push notifications without any additional configuration or dependencies.

## The Mobile Push Notification resource

Retool makes push notifications available as a [resource](../../data-sources/quickstarts/resources.mdx). This enables you to write queries that send push notifications using any Retool app or workflow. For instance, you could configure a [webhook-triggered workflow](../../workflows/guides/triggers/webhooks.mdx) to send a push notification if a PagerDuty incident is created or if the daily order volume in [Stripe](../../data-sources/guides/integrations/finance/stripe.mdx) exceeds a particular threshold.

Users must first explicitly subscribe to push notifications—you cannot automatically enroll a user.

## Topics

Push notifications use topics to represent the scope for recipients. Topics are similar in function to mailing lists—users subscribe to them based on what information they want to be notified about. Users [subscribe to push notifications](../guides/app-management/push-notifications.mdx#subscribe-users-to-push-notifications) using a subscription query in which you specify the topics to use. To send a notification, you use a query that references the relevant topic rather than managing a separate list of users.

Retool initially includes the `ALL_USERS` topic, which represents all Retool Mobile users in your organization. You can add or remove topics, and set your own, such as `SALES_TEAM` or `ENG_ONCALL`. You specify the topics to use in both the [subscribe](#subscribe) and [send](#send) queries. Once subscribed, a user can receive notifications to the topics in which they're included.

For example, the overall process to send notifications to sales managers could be:

1. You create a query to subscribe users to a set of topics, such as `SALES_TEAM` and `SALES_MANAGERS`.
2. A sales manager opens the mobile app containing the subscription query and then subscribes to those topics.
3. To send a notification, you specify the topics to use. To notify sales managers, you would use the `SALES_MANAGERS` topic.

You can also subscribe users to direct notifications on an individual basis using the `USER` topic (e.g., `USER:{{current_user.email}}`).

## Action type

The query's **Action type** determines what action to take in relation to push notifications.

### Subscribe

The **Subscribe** action type subscribes users to push notifications. You add subscribe queries to mobile apps that run automatically when launched by a user. This adds the user to the topics defined in the query. Only Retool Mobile apps can contain subscribe queries.

To subscribe a user to direct push notifications intended only for them, use `USER:{{current_user.email}}`.

### Send

The **Send** action type sends push notifications. These queries use the specified topics to represent the recipients. For instance, `SALES_TEAM` sends a push notification to all users who subscribed to the `SALES_TEAM` topic. You can send notifications directly to individual users if they subscribed with the `USER` topic with their email address.

## Deep links

Push notifications can include _deep links_ to other Retool Mobile apps and the screens they contain. This enables users to tap on a notification and be taken directly to a relevant app.

You can also include data as key-value pairs when sending a push notification which can be referenced in apps using `initialDeepLink.params`. This enables you to further customize the deep link experience. For example, you could include a user ID using `id=123` and reference it in a query to look up users with `{{initialDeepLink.params.id}}`.

`initialDeepLink.params` also includes the following properties:

| Property         | Value    | Description                                        |
| ---------------- | -------- | -------------------------------------------------- |
| `appName`        | `string` | The app to launch when the notification is tapped. |
| `releaseVersion` | `string` | The release version of the mobile app.             |
| `screen`         | `string` | The specific screen in the app to open, if set.    |

For example, a workflow could automatically send a notification whenever a new sales lead is received. The notification deep links to a sales CRM app and includes the `id` of the new lead. A recipient can tap on the notification and navigate directly to the app. By including the `id`, the app can automatically display the lead's information.

---

## The Retool Mobile app

Retool Mobile eliminates the need for compiling apps, complex distribution, and store listings with lengthy reviews. Instead of separate apps, you use a single app—Retool Mobile for iOS and Android—to browse and run apps natively. Retool Mobile apps also function as progressive web apps.

This approach simplifies deployment and makes all Retool Mobile apps instantly available. You can share links to apps so users can launch them on their device, or open them in a browser.

## How the Retool Mobile app works

The Retool Mobile app for iOS and Android uses [React Native](http://react-native.org/) to run mobile apps natively. Users can log in to their Retool organization, browse or search for mobile apps, and launch them on their mobile device.

## Device support

Retool Mobile apps are currently supported on the following OS versions. You may be able to download the app on older devices, but you will not receive updates.

| Operating system | Minimum version                  |
| ---------------- | -------------------------------- |
| iOS              | 15.5                             |
| Android          | API 23 (Android 6.0 Marshmallow) |

Some Retool functionality may be unavailable due to restrictions or limitations when run natively.

## App links

You can share links to mobile apps with users that launch automatically in the Retool Mobile app. If a user doesn't have the app installed, they are routed to the Apple App Store or Google Play. Users can enable the **Start on most recent app** option to launch the last app in use whenever opening the Retool Mobile app.

:::tip Mobile apps on the web

You can also launch Retool Mobile apps as progressive web apps (PWA). This makes it possible to use Retool Mobile apps on a wide range of devices that are unable to use the Retool Mobile app for iOS and Android (e.g., Amazon Fire tablets).
:::

---

## White-label mobile apps

Eligible Retool organizations can request _White-label Apps_: a custom-branded version of the Retool Mobile app. Retool can manage the distribution of White-label apps to users in your organization through the iOS App Store and Google Play, or you can self-manage this process.

To create a White-label App, you provide Retool with the necessary provisioning resources. Retool then generates a custom version of the mobile app for you and uploads it to the iOS App Store or Google Play.

## Eligibility

The requirements for white-label apps depend on whether you use Retool-managed or self-managed distribution, and if you will distribute apps to iOS or Android devices.

If you're an existing Enterprise customer, reach out to your deployed engineer to get started. If you're interested in upgrading to an Enterprise plan, [book a demo](https://retool.com/demo/?meeting_page_source=docs).

## Distribution options

Depending on your use case, Retool can manage the distribution of White-label apps (Retool-managed) or you can manage them directly (self-managed). In most cases, use Retool-managed distribution unless you must handle app distribution directly.

Retool manages the end-to-end process for publishing and distributing White-label apps. This includes publishing White-label apps on your behalf to the iOS App Store or Google Play. These apps are visible only to users in your organization. Your organization uses an MDM or EMM solution to manage devices on which White-label apps are installed.

Retool also manages updates and store reviews, and you have control over the release schedule.

Your organization is responsible for publishing and distributing White-label apps. Instead of publishing White-label apps on your behalf, Retool uploads app binaries to your Apple or Google Developer account. You then submit the app for review.

Self-managed distribution requires you to set up Apple or Google developer accounts, manage updates, and handle store reviews.

## Requirements

You can use this distribution option if your organization:

- Manages mobile devices using an enterprise mobility management (EMM) or MDM (mobile device management) solution.
- Only distributes apps to internal employees.

You must meet the following requirements for Retool-managed distribution of your White-label apps.

- **iOS**
  - Enrolled in [Apple Business Manager](https://business.apple.com/).
  - Use a third-party MDM solution.
- **Android**
  - Enrolled in [Managed Play Store](https://play.google.com/work).
  - Use a third-party EMM solution.

You can use this distribution option if your organization doesn't meet the requirements for Retool-managed distribution or has a use case that requires publishing White-label apps directly to the app stores.

You must meet the following requirements for self-managed distribution of White-label apps.

- **iOS**

  - Enrolled in the [Apple Developer Program](https://developer.apple.com/programs/).
  - Provide login credentials to Retool for a Developer Access level role.
  - Provide a service key to Retool for interacting with the App Store APIs.

- **Android**
  - Enrolled in the [Google Android Developer Program](https://developer.android.com/distribute/console).
  - Provide login credentials to Retool for a Developer Access level role.
  - Provide a service key to Retool for interacting with the Play Store APIs.
  -

---

## Mobile apps concept guides

import Concept from '/docs/_partials/_doctypes/_concept.mdx';

:::tip Get started with mobile apps

If you are unfamiliar with Retool mobile apps and want to get started: 

- Read the [quickstart](./quickstart) to learn about the fundamental concepts.
- Follow a [tutorial](./tutorial/) to build your first mobile app.

:::

---

## Add documentation to mobile apps

You can add documentation to an app to provide guidance and context for other users. 

## Write a README

README files are an important part of any programming project. Their purpose is to introduce the codebase to new users and help share important project details with collaborators. All mobile apps include a built-in README file for you to edit. Find the README by clicking the app's title in the toolbar.

Inside the **Edit app details** modal, there's an **Editor README** section. This text area accepts Markdown.

Content in the README is only visible to users with **Edit** or **Own** permissions on the app. When other editors open the **Edit app details** modal, they’ll see the rendered Markdown, along with the last editor to update the text, and a timestamp. Editors can click **Edit** to update the README themselves.

import Shared from '/docs/_shared/_app-documentation.mdx';

---

## Import and export apps

import Shared from '/docs/_shared/_import-export-apps.mdx';

---

## App management



---

## Send push notifications

Retool Cloud and Self-hosted organizations can send _push notifications_ to Retool Mobile users. Using the built-in **Mobile Push Notifications** resource, you write queries that send notifications to specified users from any Retool app or workflow.

Configuring push notifications is a two-part process:

- Add a query to mobile apps that subscribe users to push notifications and enables them on their device.
- Write queries in Retool apps and workflows to send push notifications to subscribed users.

Self-hosted deployments must also complete additional steps before using push notifications.

## Subscribe users to push notifications

Each user must first _subscribe_ to receive push notifications. This is done by adding a query to mobile apps that runs automatically whenever users launch the app. Open a mobile app in the app IDE and add a **Resource query**, select the **Mobile Push Notifications** resource, then select the **Subscribe** action.

You specify the topic to which the user subscribes. You can configure multiple topics, such as `ALL_USERS` or `SALES_TEAM`. You can subscribe the user to receive only direct notifications using `USER:{{current_user.email}}`.

When the query runs, it subscribes the user to push notifications. The mobile app also prompts the user to allow notifications on their device if they have not yet done so. Once subscribed, the user can receive notifications sent to relevant topics.

## Send push notifications

The **Mobile Push Notifications** resource is available anywhere you can write queries in Retool. This enables you to send notifications from any app or workflow. You can send notifications to specific users by including their email addresses or to all users. You specify the recipients and message, and then configure the query to run.

Queries for the Mobile Push Notifications resource only send when used in web apps and workflows. If you need to send push notifications from a mobile app, specify the **Send** action.

Send queries include a **Topics** field in which you add recipients. Add any topics previously used to subscribe users, such as `SALES_TEAM`. If the user subscribed to the `USER` topic that included their email address, such as `USER:{{current_user.email}}`, use `USER:jenny@example.com`.

Users can only receive notifications sent for the topics to which they subscribed.

## Configure deep links

Push notifications can include [deep links](../../concepts/push-notifications.mdx#deep-links) that, when tapped, enable users to navigate to a specific app. To include a deep link, toggle the **Configure Deep Link** setting on.

There are three settings to configure:

- **App**: The app to launch when the notification is tapped.
- **Screen**: The specific screen in the app to open. If you do not select a screen, the app's default screen is used.
- **Params**: Key-value pairs to include as available parameters for the target app.

### Deep link parameters

The `initialDeeplink.params` object contains a list of key-value pairs for each set of deep link parameters that may have been included. For example, `id=123` is available using `initialDeeplink.params.id`. You can reference deep link parameters anywhere in your mobile app and use them to control behavior, such as retrieving a specific user or prefilling an input field.

## Configure push notifications for Self-hosted deployments

If you have a Self-hosted deployment, you must obtain a _push notification API token_ from Retool and then configure additional environment variables.

First, contact our support team to request a token. Once you receive it, configure the following environment variables:

```
MOBILE_PUSH_NOTIFIER_HOST=https://spb8yl7d3j.execute-api.us-west-2.amazonaws.com
MOBILE_PUSH_NOTIFIER_API_TOKEN=(Your push notification API token)
```

---

## Preview and share mobile apps with users

import Share from "../../../_shared/_share.mdx";

---

## Custom and embedded content



---

## Display tables using Markdown

Retool Mobile supports advanced formatting by using Markdown within a Text component. While Retool Mobile doesn't have a table component, you can display tabular data using Markdown tables.

## Basic table formatting

Tables can be displayed with Markdown using pipe and dash symbols, for example:

```
| Month    | Revenue |
| -------- | ------- |
| January  | $1000   |
| February | $1200   |
| March    | $1800   |
```

The above Markdown renders as a table.

| Month    | Revenue |
| -------- | ------- |
| January  | $1000   |
| February | $1200   |
| March    | $1800   |

## Format repeatable data

Data returned from a resource query can also be rendered in a table by dynamically building the Markdown. For example, you might have a resource query named `query1` which returns the following array.

```json
[
  {
    "month": "January",
    "revenue": 1000
  },
  {
    "month": "February",
    "revenue": 1200
  },
  {
    "month": "March",
    "revenue": 1800
  }
]
```

In the Text component's **Value** field, the following would render the same table.

```
| Month    | Revenue |
| -------- | ------- |
{{query1.data.map(item => `| ${item.month} | $${item.revenue} |`).join('\n')}}
```

This code uses the [`map()` method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) of the array instance to iterate over each object in the array and format it into a string in the correct Markdown format. It then joins the new array of strings into a single string using `.join('\n')`. The same approach could be used in a transformer.

---

## Customize the theme of mobile apps

:::warning

Retool Mobile app themes function separately from Retool web app [themes](../../../apps/guides/presentation-styling/themes.mdx).

:::

You can create and manage custom styling for your mobile apps with _themes_. To customize your app's theme, click the `•••` **App actions** menu and select **App theme**.

- **Primary**: The default accent color used by most mobile components.
- **Header**: The background color for the title area of screens.
- **Buttons**: The corner style for buttons.

You can create custom themes and apply them to your mobile apps.

---

## Deploy mobile apps

The Retool Mobile app is available on the [App Store](https://apps.apple.com/us/app/retool-mobile/id1586183808) or [Google Play](https://play.google.com/store/apps/details?id=com.retool.retool). Once installed, you can log in to Retool and run mobile apps natively.

## Sign in to your Retool organization

:::tip

You can share app links to users that automatically log them in using [passwordless login](#passwordless-login).

:::

Use **Host settings** to select whether your Retool organization is on Retool Cloud or [Self-hosted](../../../self-hosted/index.mdx) (e.g., an on-premise deployment). Both [Self-hosted Retool](../../../self-hosted/index.mdx) and [Retool Cloud](https://retool.com/pricing/) organizations use the Retool Mobile app for iOS and Android to launch mobile apps natively.

If your mobile devices have limited memory, you can enable the **WebView Login** option in your organization's **Beta** settings to use an embedded WebView component for web-based logins. This reduces the Retool Mobile app's total memory usage and help prevent it from being unloaded when in the background.

## Browse and launch Retool Mobile apps

Retool Mobile for iOS and Android provides access to your Retool organization's mobile apps. When launched, it runs the most recently opened mobile app.

You can browse through the list of apps or search to find a particular mobile app. You can return to this list by pressing the **Home** button in the title bar area of the mobile app. You can also access frequently used apps in the side drawer.

## Switch environments

If your mobile app queries resources configured with [multiple environments](../../../org-users/guides/configuration/environments.mdx) (e.g., Production and Staging), you can switch between them in the sidebar of the Retool Mobile app. Environment switching is only available to users with **Edit** access to apps.

## Retool Mobile on the web

:::note

[Self-hosted Retool](../../../self-hosted/index.mdx) organizations directly control and manage PWA versions of Retool Mobile apps.

:::

You can launch Retool Mobile apps as progressive web apps (PWA). This enables the use of Retool Mobile apps on a wide range of devices that cannot run them natively using Retool Mobile for iOS and Android (e.g., Amazon Fire tablets).

Open an app link in a browser to launch a Retool Mobile app on the web. On a desktop device, the Retool Mobile app is displayed in a device frame and includes a QR code that links to the app. Scan the QR code from your mobile device to launch the app from the device.

## Share apps and invite users

:::tip Generate auto-join links for mobile-only users

You can generate an **auto-join link** that allows users to sign up from the Retool Mobile app using SSO. Users who sign up using this method are added to your organization as mobile-only users. You must [configure auto-join domains](../../../org-users/tutorials/manage.mdx#configure-auto-join-domains) to enable this option.

:::

You can [invite new users](../../../org-users/tutorials/manage.mdx#add-users) or send a link to existing users via email. Click the **Share** button in the upper-right of the app IDE to display sharing options. You can enter individual email addresses or click **Add many at once** to use a comma-separated list. You can also copy the link to an app to use elsewhere.

All Retool apps have a unique URL. Direct links open in the Retool Mobile iOS or Android app automatically. If the app is not currently installed, the user is routed to their device-specific app store listing for download.

Invited users can create an account in Retool Mobile for iOS and Android before the mobile app launches.

## Passwordless login

:::info Cloud only

Passwordless login for Retool Mobile is only available on cloud-hosted Retool.

:::

Retool Mobile includes a _passwordless login flow_ for existing users. Any existing user who opens a mobile app link is automatically logged into the Retool Mobile app. This enables you to distribute apps to your workforce without existing users needing to log in first, resulting in fewer steps.

You can also perform passwordless login if you first need to install the Retool Mobile iOS or Android app. Retool copies the app link to the clipboard when redirecting you to the device-specific app store listing. Once installed, the Retool Mobile app uses the clipboard link to complete passwordless login. This requires access to the clipboard contents. When prompted, click **Allow**.

The passwordless login flow for users who just installed Retool Mobile can automatically sign in using [passwordless login](#passwordless-login).

### Restrict user access

Your users can browse and launch any of your mobile apps by default. If your Retool organization is on a [Business or an Enterprise plan](https://retool.com/pricing/), you can [configure permission controls](../../../permissions/guides.mdx) and restrict mobile app access only to certain users or groups.

---

## Deployment



---

## Version and release apps

import Shared from '/docs/_shared/_releases-history.mdx';

---

## Provision and distribute White-label Retool Mobile apps

To create a White-label app, you provide Retool with the necessary provisioning resources. Retool then generates a custom version of the mobile app for you and uploads it to the iOS App Store or Google Play.

:::info Requirements

The requirements depend on whether Retool or your organization manages app distribution. If you're an existing Enterprise customer, reach out to your deployed engineer to get started. If you're interested in upgrading to an Enterprise plan, [book a demo](https://retool.com/demo/?meeting_page_source=docs).

Learn more in the [White-label app](../../../concepts/white-label.mdx) explanation guide.

:::

## 1. Provision a White-label app from Retool

You can request a White-label app by completing the [provisioning form](https://retoolin.tryretool.com/embedded/public/ac1ba0ab-72d4-48be-87b4-86bd305be5d2). You must provide the following provisioning resources when submitting the request.

| Resource                                     | Description                                                                                                                                                                                                                                                       | Required for Retool-managed apps | Required for self-managed apps |
| :------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------: | :----------------------------: |
| **Icon**                                     | The app icon.Must be a PNG image with a minimum resolution of 1024x1024. Width-to-height ratio must be 1:1.                                                                                                                                           |      |      |
| **Full-size logo**                           | The image displayed in various places, such as the iOS launch screen.Must be a PNG image with a minimum resolution of 320x80. Width-to-height ratio must be 4:1.                                                                                      |        |      |
| **Compact logo**                             | The image displayed in various places where the full-size logo cannot be used, such as the Android splash screen. This can be the same as the app icon.Must be a PNG image with a minimum resolution of 1024x1024. Width-to-height ratio must be 1:1. |        |      |
| **Splash screen color**                      | The splash screen background color. Must be a hex color value.                                                                                                                                                                                        |        |      |
| **Login logo**                               | The image displayed on login the screen.Must be a PNG image with a minimum resolution of 320x80. Width-to-height ratio must be 4:1.                                                                                                                   |        |      |
| **App display name**                         | The name of the app (e.g., `My Custom App`).                                                                                                                                                                                                                      |        |      |
| **App’s Store name**                         | The name to display in the store listing for the iOS App Store or Google Play. This name must be unique across all apps on the store.If your app name is not unique, combine it with your company name (e.g., `My Custom App by ACME`).               |        |      |
| **Instance URL**                             | The URL of your company’s Retool instance (e.g., `example.retool.com`).                                                                                                                                                                                           |        |      |
| **Primary app’s UUID (Single-app only)**     | The UUID to use for the White-label app (optional).                                                                                                                                                                                                               |        |      |
| **Apple Organization ID**                    | The Apple Organization ID to publish apps to the iOS App Store on your behalf.                                                                                                                                                                                    |        |     |
| **Managed Play Organization Id**             | The Google Organization ID to publish apps to Google Play on your behalf.                                                                                                                                                                                         |        |     |
| **Apple Developer Account Credentials**      | Account credentials with Developer access for your Apple Developer Account.                                                                                                                                                                                       |       |      |
| **Play Store Developer Account Credentials** | Account credentials with Developer access for your Google Developer Account.                                                                                                                                                                                      |       |      |
| **Apple Service Key**                        | The Service Key for App Store Connect.                                                                                                                                                                                                                            |       |      |
| **Google Service Key**                       | The Service Key for Google Play Console.                                                                                                                                                                                                                          |       |      |

Retool will notify you when your White-label app is ready. It is not automatically published.

## 2. Distribute a White-label app

Retool publishes White-label apps on your behalf to the iOS App Store or Google Play. These apps are visible only to users in your organization. Retool also manages updates and store reviews, and you have control over the release schedule.

To distribute Retool-managed White-label apps to devices, complete the following steps for either iOS or Android.

iOS

1. Link your MDM solution to Apple Business Manager.
2. Add your devices from Apple Configurator to Apple Business Manager. Refer to [Apple's documentation](https://support.apple.com/guide/apple-business-manager/add-devices-from-apple-configurator-axm200a54d59/web) for instructions.
3. Assign devices to your MDM server. You can either assign devices manually or configure automatic assignment.
4. Enroll your devices in your MDM solution. Management policies are applied to enrolled devices and will add them to Apple Business Manager.
5. Refer to your MDM solution's documentation to install White-label apps onto managed devices.

Android

Enroll your devices into your EMM solution. Once enrolled, users can install the White-label app onto their managed devices.

You are responsible for publishing self-managed White-label apps to the iOS App Store or Google Play. Once Retool notifies you that the app binaries have been uploaded, you can submit the app for review. After publishing, your users can install the app.

---

## Configure external authentication for White-label apps

Retool can authenticate users–internal or external to your company–into embedded apps. Organizations with [White-label apps](./index.mdx) can use custom authentication with Retool API to perform external authentication with White-label apps as well.

When your mobile user attempts to sign in, the app navigates to your custom login page. Once authenticated, your backend authorizes the user with Retool and redirects them back to the White-label app for which they now have access. The process is the same whether you're using web apps or a White-label mobile app.

Follow the [embedded apps](../../../../apps/guides/app-management/embed-apps.mdx) guide to get started.

---

## White-labeled Retool Mobile apps

[White-label apps](../../../concepts/white-label.mdx) are custom-branded versions of the Retool Mobile app of which eligible organizations can request. Retool can manage the distribution of White-label apps to users in your organization through the iOS App Store and Google Play, or you can self-manage this process.

---

## Manage White-label app updates

Your White-label app functions in the same way as the Retool Mobile app. You can continue to make incremental changes to your mobile app (e.g., editing existing apps and queries) without needing to publish an update.

You must publish a new version of your White-label app to the iOS App Store or Google Play if you need to:

- Make use of new functionality in Retool Mobile.
- Change your app's name, image assets, or icon.

---

## Mobile app error reporting and observability

import Observability from "../../_shared/_observability.mdx";
import Errors from "../../_partials/_app-errors.mdx";
import Filtering from "../../_shared/_filtering-routing.mdx";

---

## Manage date and time values in web apps

import Shared from '/docs/_shared/_time-zones.mdx';

---

## Upload files and images in mobile apps

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

Retool provides a number of components that enable users to upload files and images in mobile apps:

- File Input
- [Image Input](../../reference/components/media/image-input)

These components have several configuration options that allow you to control what users can upload.

:::caution File size limit

The maximum supported file size for file uploads is 40MB.

:::

## Add file upload functionality

Add a File Input component to the canvas. This enables users to upload files from the mobile app.

### Accepted file types

Use the **File types** option to specify the MIME types to allow for upload. Retool provides three categories of file types from which you can select.

The **Documents** option contains a list of MIME types for common file types, such as PDFs and Microsoft Word documents.

```json Document MIME types
[
  "text/*",
  "application/*",
  "application/pdf",
  "application/msword",
  "application/vnd.ms-excel",
  "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  "application/json",
  "application/rtf",
  "application/xml"
]
```

The **Images** option allows the upload of all images that use the `['image/*']` MIME type.

The **Any** option uses `['*/*']` as the specified MIME type, allowing for the upload of any file.

import FxSvg from '/img/icons/fx.svg';

:::tip Specify your own MIME types

You can provide your own list of MIME types to accept. Click the  button and specify an array of MIME type values.

:::

## Add image upload functionality

Add an Image Input component to the canvas. This button enables users to select an image to upload.

### Input method

You can configure the Image Input component's **Input method** option to specify whether users can upload images from their device's photo library, capture and upload images with the camera, or allow the user to choose.

### Resolution

To reduce file size and improve performance, Retool can scale images during upload. Select **Low**, **Medium**, or **High** to specify the resolution size to use. You can also prevent resolution changes with **Original**.

### Compress photos

Retool can also compress images for file size and performance. Enabling this option results in images that are 50% smaller in size but with minimal loss of quality.

### Single or multiple selection

You can specify whether users can upload a single image or multiple images.

If you allow multiple images, you can also specify a minimum or maximum number of images to allow.

## Reference uploaded file and image data
The Image Input and File Input components temporarily save captured data as blobs with `blob:` or `file://` URI strings. You can reference this blob elsewhere in your app (e.g., to preview in an [Image](../../reference/components/media/image.mdx) component) or upload captured images or files to a data store.

:::tip Convert blobs to Base64-encoded strings

You can use [utils.getDataByObjectURL()](../../../queries/reference/libraries/utils.mdx#utilsgetdatabyobjecturl) to convert blobs into a Base64-encoded string for other uses.

:::

The `value` property for the [Image Input](../../reference/components/media/image-input.mdx) and [File Input](../../reference/components/forms/file-input.mdx) components contains an array of `blob:` or `file://` values, as the components support multiple selections. The `files` property is an object with more information about the uploaded images. `value` is always an array, regardless of whether a user uploads a single file or multiple images. Single-image uploads are accessible using `value[0]`.

## Improved version of File Input

The improved File Input component offers users the ability to upload multiple files at a time, and the `value` state property is an array of blob URLs instead of a single Base64-encoded URL. The `value` property is a `string[]`, not an `object[]`.

export function ArcadeEmbed() {
  return (
    
      
    
  )
}

## Save uploaded files and images

You can reference `value` in queries to [store files in a data store](../../../queries/guides/files.mdx), such as Retool Storage or [Amazon S3](../../../data-sources/guides/integrations/object-file-store/amazon-s3.mdx).

:::tip Save files directly to Retool Storage

You can enable the **Upload file to Retool Storage** option for the component to automatically store the file in Retool Storage.

:::

---

## Forms and inputs



---

## Define option lists

import Shared from '/docs/_shared/_define-option-lists.mdx';

---

## Accept digital signatures

import FxSvg from '/img/icons/fx.svg';

You can use the [Signature](../../reference/components/forms/signature.mdx) component in mobile apps to collect digital signatures from customers.

## Collect a signature

Add the Signature component to the canvas then press the signature to present the input field. The component uses landscape orientation by default to maximize the available space.

The Signature component temporarily saves a captured signature in PNG format as a blob with a `blob:` or `file://` URI string. You can reference this blob elsewhere in your app (e.g., to preview in an [Image](../../reference/components/media/image.mdx) component) or upload captured signatures to a data store.

## Save uploaded signatures

:::important
Retool recommends saving signatures with [utils.getDataByObjectURL()](../../../queries/reference/libraries/utils.mdx#utilsgetdatabyobjecturl), which converts blobs into a Base64-encoded string. 
:::

You can reference the `value` property of Signature in queries to upload and store the signature in a data store, such as Amazon S3 or Retool Storage. 

### Upload a signature to Retool Storage

To save a signature to Retool Storage, add a JavaScript query to convert the blob URL to a Base64-encoded string. 

In the IDE, from your mobile app that contains a Signature component:

1. Capture a signature.
2. From the Code tab, select **+** and add a **JavaScript query** to the screen. 
3. Add the following code snippet to the query, and replace `signature1` in the following example code with the name of your signature component.
   ```   
   const base64String = await utils.getDataByObjectURL(signature1.value);
   return base64String;
   ```

export function ArcadeEmbed() {
  return (
    
      
    
  )
}

4. Click **+** to add a **Resource query** to the screen. 
5. Choose **Retool Storage** as the **Resource**.
6. Select **Upload file** as the action type.
7. Click the  button next to the **File content** field and enter `{{ query1.data }}`. Replace `query1` with the name of your JavaScript query.
8. Give the file a name, and click **Save**. 
9. Click **Run**. 

export function ArcadeEmbed_rq() {
  return (
    
      
    
  )
}

The **Output** section of the query displays the Base64-encoded string that you uploaded to **Retool Storage**. 

To verify that you've correctly captured the signature image:

1. Navigate to the **Retool home** button and select **Resources** from the dropdown. 
2. Select **Retool Storage**.
3. Find the signature file you uploaded to Retool Storage, and select **Download** from the  menu.
4. Open the downloaded file and copy the Base64 output.
5. In the IDE, click the **Components** tab.
6. Click **+** to add an Image component to the screen. 
7. In your mobile app, select the Image component to open the Inspector. 
8. Paste the Base64-encoded string into the **Image source** URL field. 

The image displayed should look the same as the signature you captured. 

export function ArcadeEmbed_verify() {
  return (
    
      
    
  )
}

### Upload a signature to an external data store
Queries that upload to data stores, such as Google Cloud Store and Amazon S3, require the correct MIME type and Base64-encoded data. Captured signatures use the `image/png` MIME type. You can use [utils.getDataByObjectURL()](../../../queries/reference/libraries/utils.mdx#utilsgetdatabyobjecturl) to convert blobs into a Base64-encoded string.

---

## Retool Mobile hardware integrations



---

## Read and write NFC tag data

Retool Mobile can read data from NFC tags and supports writing data using NDEF ([NFC Data Exchange Format](https://w3c.github.io/web-nfc/#dfn-ndef-record)) records.

## Read data using the NFC Reader mobile component

The [NFC Reader](../../reference/components/media/nfc-reader.mdx) mobile component uses a mobile device's native NFC reader interface without any additional configuration required. When a user presses the button, the native NFC reader appears and scans the NFC tag. The scanned data is then available using the component's `value` property.

This method for reading NFC data requires no additional configuration but often results in the native interface obscuring the app.

## Read and write data using the NFC resource

You can use the **NFC (Near-field communication)** resource for mobile apps to read and write NFC tag data. Unlike the NFC Reader mobile component, NFC resource queries don't use the native NFC reader interface. When the query is triggered, the NFC resource reads or writes NFC data seamlessly, which is better suited for frequent use of NFC tags.

### 1. Create a resource query

First, create a query that uses the **NFC** resource.

1. Click  to open the **Code** tab.
2. Click **+** to add a query.
3. Select **Resource query**.
4. Select the **NFC** resource.

### 2. Select the NFC method

Select the **Read** action to read NFC data. No additional configuration is required. 

Read data using an NFC resource query.

Select the **Write** action to write data to NFC tags. This is stored as a [NDEF TEXT record](https://w3c.github.io/web-nfc/#dfn-ndef-record).

Write data using an NFC resource query.

---

## Capture data with ProGlove scanners

Retool Mobile supports the use of [ProGlove](https://proglove.com) scanners with Android devices. Once configured, you use the [ProGlove mobile component](../../reference/components/media/proglove.mdx) to capture events from, initiate pairing with, and disconnect from ProGlove scanners.

## Prerequisites

:::tip

ProGlove shares common APIs with [Zebra](./zebra/index.mdx) for interoperability but it functionally distinct. You can use ProGlove scanners with any supported Android device.

:::

The ProGlove [INSIGHT Mobile](https://docs.proglove.com/en/insight-mobile--android-.html) app manages the integration between the Android device and ProGlove scanners. To use the ProGlove mobile component, a ProGlove administrator must:

- Install and set up the INSIGHT Mobile app on the Android device.
- Configure the INSIGHT Mobile [intent integration path](https://docs.proglove.com/en/intent-api---basic-integration.html#select-the-intent-integration-path).

Once complete, Retool Mobile can function with ProGlove scanners.

## 1. Configure the ProGlove component

First, add the **ProGlove** component to your mobile app. You use this component to pair and disconnect ProGlove scanners, and receive captured data.

Adding the ProGlove component.

When a ProGlove scanner captures data, it sends it as a ProGlove [Intent](https://docs.proglove.com/en/intent-api---basic-integration.html#barcode-scan-intent-structure) object. The Intent object contains the `com.proglove.api.extra.BARCODE_DATA` key that represents the data in the scanned barcode, and a `com.proglove.api.extra.BARCODE_SYMBOLOGY` key that represents the barcode type. Review [ProGlove's documentation on barcode symbologies](https://docs.proglove.com/en/symbology-settings.html) to see all possible values for `BARCODE_SYMBOLOGY`.

```json title: "Example ProGlove Intent"
{
  "com.symbol.datawedge.decoded_mode": "single_decode",
  "com.proglove.api.extra.BARCODE_SYMBOLOGY": "CODE 128",
  "com.proglove.api.extra.BARCODE_DATA": "1234567890",
  "com.motorolasolutions.emdk.datawedge.label_type": "LABEL-TYPE-CODE128",
  "com.symbol.datawedge.data_string": "1234567890",
  "com.motorolasolutions.emdk.datawedge.data_string": "1234567890",
  "com.motorolasolutions.emdk.datawedge.source": "scanner",
  "com.symbol.datawedge.label_type": "LABEL-TYPE-CODE128",
  "com.symbol.datawedge.source": "scanner"
}
```

The ProGlove component functions as a listener and receives the Intent, which triggers the **Capture** event. The component's `data` property is set to the received Intent. You can reference this property almost anywhere in Retool, such as `{{ proGlove1.data }}`.

You can also add a **Capture** event handler that runs whenever data is captured. For example, you can use the **Run script** action to set the value of a [Text](../../reference/components/text/text.mdx) component using JavaScript.

```js
text1.setValue(JSON.stringify(proGlove1.data));
```

Configure the ProGlove component event handler.

If you want to extract data from the barcode, use the `com.symbol.datawedge.data_string` key value. For example: `zebraDataWedgeReader1.data['com.symbol.datawedge.data_string']`.

## 3. Pair a ProGlove scanner

The ProGlove component initially displays a **Pair ProGlove** button. This action can only be performed when running the app on an Android device. When pressed, the INSIGHT Mobile app appears and performs the pairing process where you scan the Android device's QR code with the scanner. Once a scanner is paired, you can then use it to capture data.

The component's `scannerState` property reflects the current scanner connection.

| Value          | Description                                                  |
| -------------- | ------------------------------------------------------------ |
| `DISCONNECTED` | Scanner is disconnected.                                     |
| `CONNECTED`    | Scanner is connected.                                        |
| `CONNECTING`   | Scanner is connecting.                                       |
| `ERROR`        | An error occurred when attempting to connect to the scanner. |
| `RECONNECTING` | Scanner is reconnecting.                                     |
| `SETTING_UP`   | The scanner is currently being set up.                       |
| `SEARCHING`    | Searching for a scanner.                                     |

## Disconnect a scanner

You can disconnect a paired ProGlove scanner by pressing the **Disconnect** button. The `scannerState` property value changes to `DISCONNECTED` once done.

---

## Capture data using Zebra Android devices

import Zebra from "./_zebra.mdx";

Retool uses the [Zebra DataWedge APIs](https://techdocs.zebra.com/datawedge/11-3/guide/api/overview/) to receive and capture events using the [Zebra DataWedge Reader](../../../reference/components/media/zebra.mdx) component. To see an example app using the Zebra APIs, try out the [Inventory Management with Zebra Scanner](https://retool.com/templates/zebra-warehouse-management) template.

## Prerequisites

For security purposes, Zebra [controls access to the DataWedge Intents APIs](https://techdocs.zebra.com/datawedge/11-3/guide/programmers-guides/secure-intent-apis/). Zebra administrators must first create a Zebra DataWedge profile. You can create this profile on the **Zebra DataWedge setup** screen within the **Settings** menu. Open the top left menu when viewing the Retool Mobile app on a Zebra device and select **Settings** > **Zebra DataWedge setup** to get started.

This screen contains information for debugging your DataWedge profile, as well as a button to automatically configure a profile for Retool and an output of events:

Retool Mobile top left menu

Retool Mobile settings menu, showing an option for Zebra DataWedge setup

Zebra DataWedge Setup screen

Alternatively, administrators can [create a Zebra DataWedge profile](https://techdocs.zebra.com/datawedge/11-3/guide/api/createprofile/) with the following configuration to add the Retool Mobile app as an approved DataWedge application.

| Setting             | Value                     |
| ------------------- | ------------------------- |
| **Associated app**  | `com.retool.retool`       |
| **Activity**        | `*`                       |
| **Intent output**   | **Enabled**               |
| **Intent action**   | `com.retool.zebra.ACTION` |
| **Intent category** | Clear or leave unset      |
| **Intent delivery** | **Broadcast intent**      |

Once configured, the Retool Mobile app is able to receive captured data and provide it to your mobile apps. Refer to the [Zebra DataWedge APIs documentation](https://techdocs.zebra.com/datawedge/11-3/guide/api/) for more information on approved apps and profiles.

## Receive captured data in Retool Mobile

The [Zebra DataWedge Reader](../../../reference/components/media/zebra.mdx) component allows your Retool Mobile apps to receive this data and use it elsewhere. Add this component to your mobile app to receive captured Zebra data and configure [event handlers](../../interaction-navigation/event-handlers.mdx) to perform actions with it.

When a Zebra device captures data, it sends it as a DataWedge [Intent](https://techdocs.zebra.com/datawedge/11-3/guide/output/intent/#theintentobject) object. The Zebra DataWedge Reader component functions as a listener and receives the Intent, which triggers the **Capture** event. The component's `data` property is set to the received Intent.

The intent object contains a `com.symbol.datawedge.data_string` key that represents the data in the scanned barcode, and a `com.symbol.datawedge.label_type` key that represents the barcode type. Review [Zebra's documentation on the intent object](https://techdocs.zebra.com/datawedge/11-3/guide/output/intent/#theintentobject) to see all possible values for `label_type`. The intent object also contains various other keys depending on the model of your Zebra device. See below for a sample intent object:

```
{
  "com.symbol.datawedge.decoded_mode": "single_decode",
  "v2API": true,
  "com.motorolasolutions.emdk.datawedge.label_type": "LABEL-TYPE-CODE128",
  "com.symbol.datawedge.data_string": "1234567890",
  "com.symbol.datawedge.data_dispatch_time": 1701754038282,
  "com.motorolasolutions.emdk.datawedge.data_string": "1234567890",
  "com.motorolasolutions.emdk.datawedge.source": "scanner",
  "com.symbol.datawedge.label_type": "LABEL-TYPE-CODE128",
  "com.symbol.datawedge.source": "scanner"
}
```

You configure event handlers to trigger queries or perform actions when events occur. Click **+ Add** in the **Interaction** section of the Inspector to add an event handler.

For example, you can use the **Run script** action to set the value of a [Mobile Text](../../../reference/components/text/text.mdx) component using JavaScript. This is useful when testing your apps on Zebra devices. This example wraps the `data` property in `JSON.stringify()` to display it as a string.

```js
text1.setValue(JSON.stringify(zebraDataWedgeReader1.data));
```

If you want to extract data from the barcode, access the `com.symbol.datawedge.data_string` key on the data object. For example: `zebraDataWedgeReader1.data['com.symbol.datawedge.data_string']`.

## Hide the Zebra component button

The Zebra DataWedge Reader component initially displays a **Toggle scan** button that can trigger the embedded capture hardware, such as a scanner. If your Zebra devices already have a dedicated hardware button, you can hide the component. In the **Layout** section of the Inspector, set the component's **Hidden** setting to `true`.

Your mobile app only needs to contain a Zebra DataWedge Reader component to receive captured data, but it doesn't need to be visible.

---

## Build mobile apps for Zebra Android devices

import Zebra from "./_zebra.mdx";

---

## Print to Zebra label printers

You can use the **Zebra Printer** resource for mobile apps to write queries for Zebra Android devices that print to Bluetooth Zebra label printers.

## 1. Create a resource query

First, create a query that uses the **Zebra Printer** resource.

1. Click  to open the **Code** tab.
2. Click **+** to add a query.
3. Select **Resource query**.
4. Select the **Zebra Printer** resource.

## 2. Select the print method

Retool can send print jobs to a Bluetooth Zebra printer by either broadcasting to its MAC address or directly to one that is currently paired. Select the desired **Method** in the query.

Use **Broadcast to MAC address** to send print jobs to a Bluetooth Zebra printer and enter its MAC address, such as `00:23:45:67:89:AB`.

Send print jobs to a specified printer using its MAC address.

Select **Send to paired device** to send print jobs to a Zebra printer that is currently paired with the Zebra Android device. 

Send print jobs to a paired printer.

A ZPL (Zebra Programming Language) string is a series of commands for printing to Zebra printers. The exact ZPL string you provide is dependent on the Zebra printer in use.

The following example is a ZPL string that uses a `{{ }}` dynamic expression to reference a the current user's email address.

```text title="ZPL string example"
^XA
^FO50,50^A0N50,50^FD{{ current_user.email }}^FS
^XZ
```

Refer to Zebra's [ZPL command](https://supportcommunity.zebra.com/s/article/ZPL-Command-Information-and-DetailsV2) documentation to learn more about writing ZPL strings.

---

## Event handlers

import Shared from '/docs/_shared/_event-handlers.mdx';

---

## Interaction and navigation



---

## Assemble mobile screens

Retool Mobile organizes mobile components into separate screens that you create for different purposes. Users navigate between screens using the tab bar or by interactions that trigger event handlers, such as pressing a button or selecting an item from a list.

## Manage screens

When editing a Retool Mobile app, the [app IDE](../../../apps/concepts/ide.mdx) includes an additional _mobile panel_ on the left. Use the **Screens** section of the mobile panel to select, add, or delete screens from your mobile app.

To add a new screen, click the **+** button. To delete an existing screen, click the `•••` icon next to the screen, then select **Delete**.

Each screen has a _title_ and _name_ that you can update in the Inspector.

- The _title_ (e.g., `Screen 1`) is the text displayed in the app, similar to a web component's label. It appears in the title bar area of your app and in the tab bar at the bottom (if visible).
- The _name_ (e.g., `screen1`) is used within the editor as the reference when you configure settings or write queries.

You configure the selected screen using the Inspector (the **Inspect** tab) in the right panel.

## Navigate between screens

You can configure navigation between screens for your mobile app using the tab bar, configuring event handlers, or with JavaScript.

### Navigate with the tab bar

:::note

The first tab in the list is also the default screen that is first shown to users when opening the app.

:::

Mobile apps automatically include a _tab bar_ at the bottom of the app if **Add to tab bar** is enabled on at least two screens. Pressing a tab navigates to the screen associated with it.

You customize the tab bar in the **Tab** section of the Inspector. Click and drag to change the order of tab. The tab bar displays the screen name by default. You can click on each tab to set a custom icon and title for each tab.

### Navigate using event handlers

Retool uses [event handlers](event-handlers.mdx) to trigger queries or other actions in response to user events on mobile components. You can create **Navigation** event handlers that navigate to a screen when a specified action occurs.

| **Name**               | **Description**                                           |
| ---------------------- | --------------------------------------------------------- |
| **Navigate to screen** | Navigate to the specified screen.                         |
| **Open Modal**         | Open a modal using the specified screen.                  |
| **Back**               | Go back to the previous screen.                           |
| **Back to root**       | Navigate back to the first screen.                        |
| **Open bottom sheet**  | Open a Bottom Sheet that slides from the bottom of the viewport. |
| **Select tab**         | Navigate to a screen and update the tab bar.              |

You can trigger **Navigation** events almost anywhere in a mobile app that supports event handling, such as a button press or query failure.

#### Tablet mode navigation

Event handlers in tablet mode have an additional option for adding screens as detail views. When building an app for tablets, select the event handler and enable the **Add as detail view in tablet mode** option. From there, you can select different view settings for the screen.

### Navigate using JavaScript

You can [write JavaScript](../../../queries/quickstart.mdx) to control navigation using `navigator.navigateTo()` and the name of the screen:

```js title="Navigate to a screen"
navigator.navigateTo("screen1");
```

## Trigger actions with event handlers

You can configure screens with event handlers that trigger actions based on certain interactions or using additional buttons in the title bar.

Use the **Screen events** section of the Inspector to configure a screen with one of the following event handlers. Click **+ Add** to add an event handler or click an existing one to edit. You can also duplicate or delete event handlers by clicking the **...** icon.

| **Name**    | **Description**                              |
| ----------- | -------------------------------------------- |
| **Load**    | The screen is loaded.                        |
| **Visible** | The screen becomes visible.                  |
| **Hidden**  | The screen becomes hidden.                   |
| **Unload**  | The screen is unloaded.                      |
| **Refresh** | The user performs a pull-to-refresh gesture. |

### Load and unload events

A **Load** event occurs when a screen is loaded into the app's navigation. This occurs when:

- You add a screen to the tab bar in the app IDE.
- A user first navigates to a screen during an app session.
- A modal screen appears.

Load events are useful if you need to perform a one-time action in a particular screen, rather than trigger the action every time.

An **Unload** event occurs when a screen is unloaded from navigation. This occurs when:

- You remove a screen to the tab bar in the app IDE.
- A modal screen is dismissed.

Modal screens trigger **Load** and **Unload** events since they are loaded and unloaded into the app's navigation on-demand.

### Visible and hidden events

A **Visible** event occurs whenever a screen becomes visible to a user. A **Hidden** event occur when a screen is no longer visible. These events occur when users navigate the app and move from screen to screen.

### Refresh events

Retool Mobile supports the pull-to-refresh gesture (swipe and pull down on a screen). This triggers a **Refresh** event. A common use for this is to reload data, but you can also configure a **Refresh** event to perform any type of supported action.

You can provide users with visual feedback that data is currently being refreshed. Set the **Refreshing** property in the **Interaction** section of the Inspector to a truthy value. For example, queries include the `isFetching` property that reflects whether it is actively running.

## Action buttons

You can configure _action buttons_ that appear in the title bar area. Use the **Actions** section of the Inspector for a selected screen to configure action buttons.

The title bar supports a maximum of three action buttons—one left and two right. You can set a custom icon and text for action buttons, and select the action to perform.

## Display screens as modals or sheets 

Mobile apps can also display a screen as a modal or bottom sheet. These appear over the current screen without affecting navigation. As such, they contain controls to dismiss the screen instead of navigation. 

Modals and sheets must be invoked using an event handler, such as a button press. You configure modals and sheets using the **Navigation** event handler action. 

import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";

A _modal_ appears as a full-size screen and contains a **Done** button to dismiss. Use the **Open modal** method and select a screen to use. 

A _bottom sheet_ appears as a sliding popover that originates from the bottom of the viewport. It is only partially visible at first and can be dragged vertically to change its size. To dismiss, drag the sheet to the bottom of the viewport. 

Use the **Open bottom sheet** method and select a screen to use.

---

## Share data between mobile app screens

Mobile app screens cannot directly interact with each other. You can use globally scoped variables or localStorage to pass data between pages.

## Share data using global variables

Variables temporarily store data for the duration of the user's app session. They can also include an optional initial value. Learn more about [variables](../../../queries/guides/store-temporary-data.mdx).

To create a global variable, navigate to the **Code** tab and click **+ > Variable**. As the variable is globally scoped, you can update its value from any page using [event handlers](../../../apps/guides/interaction-navigation/event-handlers.mdx), or with the `setIn()` and `setValue()` [JavaScript methods](../../../queries/reference/objects/variable.mdx#methods).

For example, you can use the List Collection component's **Click** event handler to store the selected item in a global variable. You can then reference the global variable in another screen.

Store page data in a global variable.

You can then reference the global variable anywhere else within the mobile app.

 
Reference a global variable for use in another screen.

Once the user leaves the mobile app, the variable reverts to its initial value.

## Store page data in localstorage

:::warning

localStorage does not encrypt data. Only use localStorage to store nonsensitive information. 

:::

[localStorage](../../../queries/guides/store-temporary-data.mdx) temporarily stores data in the device's localStorage. Unlike variables, localStorage is a persistent data store. Provided the user continues to use the same browser and has not cleared their browsing history or cache, data remains available.

Use [event handlers](../../../apps/guides/interaction-navigation/event-handlers.mdx) or the `setValue()` [JavaScript method](../../../queries/reference/objects/localstorage.mdx#methods) to store data in localStorage. You can also clear app-specific data using `clear()`.

---

## Display data with Collection mobile components

You can present data using Card Collection and List Collection components that [dynamically map data](../forms-inputs/option-lists.mdx) and display it using prebuilt layouts. These components use **Mapped options** settings in the Inspector to configure item properties and how they appear.

## Display cards

The Card Collection mobile component display items in a card layout. It combines an image or icon with text information.

You can control the appearance of cards using the **Data Layout** settings in the Inspector. Options include:

- **Style**: **Flat** renders cards without a background and applies rounded corners to images. **Elevated** renders cards with a distinct border, shadow, and padding.
- **Scroll**: **Vertical** renders cards in a vertically scrolling column. **Horizontal** renders cards in a horizontally scrolling row.
- **Size**: **Full** renders full-size cards. **Half** renders half-size cards. If **Scroll** is set to **Vertical**, cards are displayed as either a single column or two-column grid.

You can also configure the image dimension ratio, such as **1:1** or **4:3** to display images to best fit your needs.

## Display lists 

The List Collection component renders each row of data using a list layout. It combines an image or icon with text information.

You can control the appearance of list items using the **Data Layout** settings in the Inspector. Options include:

- **Style**: **Flat** renders list items with no margin or background, and can include an optional separator between list items. **Elevated** renders list items with a distinct border, shadow, and padding.

## Assemble a custom collection

The Custom Collection mobile component allows you to build your own collection using other mobile components. This gives you control over which mobile components to include.

You add mobile components to a Custom Collection by clicking the **+** button or dragging them into the collection. You also use `item` and `i` to reference the current data source and set these as values for each mobile component.

## Select collection items

You can configure event handlers to trigger an action when a user selects a collection item, such as navigating to another screen or triggering a query. When a user selects an item, the item's data is stored in the collection's `selectedItem` property. This allows you to use details about a selected item elsewhere.

For example, each item contains a URL, `item.url`, to a web page that should open when selected. To achieve this:

1. Select a collection and click **+ Add** in the **Interaction** settings to add an event handler.
2. Set the **Action** to **Open URL**
3. Set the **URL** to `{{ self.selectedItem.url }}`

When an item is selected in a collection, the mobile app opens the web page using the `URL` of the selected item.

---

## Group components with the Mobile Container component

Retool Mobile apps arrange [mobile components](../../reference/components/index.mdx) in _column_ (vertical) and _row_ (horizontal) layouts. [Container](../../reference/components/layout/container.mdx) components include additional layout settings to control the layout of nested components.

## Horizontal layouts

You can arrange nested components horizontally:

1. Click **+** in the **Components** section and add a **Container** mobile component to your mobile app.
2. Add some mobile components to this Container, or drag existing ones into it.
3. Configure the Container to arrange nested mobile components in a row layout by selecting a **Layout type** of **➜**.

## Gap and padding

You can use **Gap** and **Padding** settings to fine-tune their layout.

- **Gap** controls the space between nested mobile components.
- **Padding** controls the space surrounding all nested mobile components.

You may need to adjust these settings whenever you make significant changes to your app's layout.

If you use nested mobile components extensively, you can use **Gap** and **Padding** settings to fine-tune their layout.

- **Gap** controls the space between nested mobile components.
- **Padding** controls the space surrounding all nested mobile components.

You may need to adjust these settings whenever you make significant changes to your app's layout.

## Spacing

Use the [Divider](../../reference/components/layout/divider.mdx) and [Spacer](../../reference/components/layout/spacer.mdx) mobile components to visually separate vertical areas of your mobile app with dividing lines or empty blocks of space.

---

## Customize mobile app style

You can customize the appearance and layout of mobile apps in a number of ways. Use Collections to display data using prebuilt card and list layouts, or create your own with mobile components. Configure your app's layout and tailor the design to meet your needs, and include additional UI elements to further extend functionality.

## Customize the layout with containers

Retool Mobile apps arrange [mobile components](../../reference/components/index.mdx) in _column_ (vertical) and _row_ (horizontal) layouts. [Container](../../reference/components/layout/container.mdx) components include additional layout settings to control the layout of nested components.

### Horizontal layouts

You can arrange nested components horizontally:

1. Click **+** in the **Components** section and add a **Container** mobile component to your mobile app.
2. Add some mobile components to this Container, or drag existing ones into it.
3. Configure the Container to arrange nested mobile components in a row layout by selecting a **Layout type** of **➜**.

### Gap and padding

You can use **Gap** and **Padding** settings to fine-tune their layout.

- **Gap** controls the space between nested mobile components.
- **Padding** controls the space surrounding all nested mobile components.

You may need to adjust these settings whenever you make significant changes to your app's layout.

If you use nested mobile components extensively, you can use **Gap** and **Padding** settings to fine-tune their layout.

- **Gap** controls the space between nested mobile components.
- **Padding** controls the space surrounding all nested mobile components.

You may need to adjust these settings whenever you make significant changes to your app's layout.

### Spacing

Use the [Divider](../../reference/components/layout/divider.mdx) and [Spacer](../../reference/components/layout/spacer.mdx) mobile components to visually separate vertical areas of your mobile app with dividing lines or empty blocks of space.

## Use collections to present data

You can present data using Card Collection and List Collection components that [dynamically map data](../forms-inputs/option-lists.mdx) and display it using prebuilt layouts. These components use **Mapped options** settings in the Inspector to configure item properties and how they appear.

You can also create your layout of mobile components with Custom Collection.

### Cards

Card Collection display items in a card layout. It combines an image or icon with text information.

You can control the appearance of cards using the **Data Layout** settings in the Inspector. Options include:

- **Style**: **Flat** renders cards without a background and applies rounded corners to images. **Elevated** renders cards with a distinct border, shadow, and padding.
- **Scroll**: **Vertical** renders cards in a vertically scrolling column. **Horizontal** renders cards in a horizontally scrolling row.
- **Size**: **Full** renders full-size cards. **Half** renders half-size cards. If **Scroll** is set to **Vertical**, cards are displayed as either a single column or two-column grid.

You can also configure the image dimension ratio, such as **1:1** or **4:3** to display images to best fit your needs.

### Lists

List Collection renders each row of data using a list layout. It combines an image or icon with text information.

You can control the appearance of list items using the **Data Layout** settings in the Inspector. Options include:

- **Style**: **Flat** renders list items with no margin or background, and can include an optional separator between list items. **Elevated** renders list items with a distinct border, shadow, and padding.

### Custom Collection

Custom Collection allows you to build your own collection using other mobile components. This gives you control over which mobile components to include.

You add mobile components to a Custom Collection by clicking the **+** button or dragging them into the collection. You also use `item` and `i` to reference the current data source and set these as values for each mobile component.

### Select collection items

You can configure event handlers to trigger an action when a user selects a collection item, such as navigating to another screen or triggering a query. When a user selects an item, the item's data is stored in the collection's `selectedItem` property. This allows you to use details about a selected item elsewhere.

For example, each item contains a URL, `item.url`, to a web page that should open when selected. To achieve this:

1. Select a collection and click **+ Add** in the **Interaction** settings to add an event handler.
2. Set the **Action** to **Open URL**
3. Set the **URL** to `{{ self.selectedItem.url }}`

When an item is selected in a collection, the mobile app opens the web page using the `URL` of the selected item.

## Additional UI elements

Retool Mobile event handlers include actions to display supplemental UI elements with additional actions or information.

Action sheets and alerts are modals that provide additional information and event handler actions for users to select. These actions allow users to trigger queries, navigate to a screen, etc. Both Action sheets and alerts can also include a title and description, allowing you to provide more context to users.

### Display an action sheet

An _action sheet_ is an overlay modal that appears at the bottom of the screen. It contains a title and description, along with a list of actions from which a user selects.

To create an action sheet:

1. Add a new event handler.
2. Set the **Action** to **Action sheet**.
3. Click **+ New** to add a new action to the sheet.

You configure event handlers for each menu item in an action sheet.

### Reload data with pull-to-refresh

Retool Mobile supports the pull-to-refresh gesture on screens by configuring the **Refresh** event handler. This allows users to trigger a specific action by performing the gesture on the specified screen.

A common use for this is to reload data in the current screen. If your screen contains components that use data from a query, you can configure the event handler to trigger the query. This reloads the query data and updates the components, refreshing the app with the latest data.

To enable pull-to-refresh on a selected screen:

1. Click **+ Add** to create an event handler.
2. Select the **Refresh** event.
3. Select the **Trigger** action and specify the query to run.

### Display an alert modal

An _alert_ is a modal that appears at the center of the screen. It contains a title and description, along with a maximum of two actions.

To create an alert:

1. Add a new event handler.
2. Set the **Action** to **Alert**.
3. Click **+ New** to add a new action to the alert.

### Display in-app notifications

:::note

Retool Mobile notifications are in-app banners. They are not push notifications.

:::

A _notification_ is an informational modal that appears at the bottom of the screen.

To create a notification:

1. Add a new event handler.
2. Set the **Action** to **Notification**.
3. Specify the **Title**, **Description**.
4. Select the **Type** of notification

The notification's **Type** reflects the severity of the notification, changing the icon and color used. You can also control the duration that notifications remain on the screen.

## Apply custom theme styles

:::warning

Retool Mobile app themes function separately from Retool web app [themes](../../../apps/guides/presentation-styling/themes.mdx).

:::

You can create and manage custom styling for your mobile apps with _themes_. To customize your app's theme, click the `•••` **App actions** menu and select **App theme**.

- **Primary**: The default accent color used by most mobile components.
- **Header**: The background color for the title area of screens.
- **Buttons**: The corner style for buttons.

You can create custom themes and apply them to your mobile apps.

---

## Layout and structure



---

## Retool Mobile offline functionality



---

## Offline assets

The **Offline Assets** app setting in Retool Mobile allows you to store PDF files that can be retrieved and viewed offline, or in situations where internet connectivity is limited.  

## Create a new offline asset

:::note
PDF is currently the only file type supported for offline assets. 
:::

To create a new offline asset, upload a PDF URL to your mobile app from **App settings > Offline Assets**. 
1. Click the **App Settings** tab. 
2. Select **Offline Assets**. 
3. Click the **Add new** button.
4. Populate the **Name** and **URL** of the PDF.
5. Click **Add**. 

export function ArcadeEmbed_offline() {
  return (
    
      
    
  )
}

## View an offline asset with PDF Viewer

:::warning
To view your PDF with the PDF Viewer component, your URL must have a CORS policy that allows retool.com to access the PDF file. CORS policies vary between cloud and self-hosted (for example, `https:{domain}.retool.com` for cloud-hosted organizations, and `FQDN` for self-hosted organizations). To view an example CORS policy, refer to [Configure the CORS policy](../../../data-sources/guides/integrations/object-file-store/amazon-s3.mdx#configure-the-cors-policy). 

You can also upload a PDF as a Retool Storage resource, and select **Copy URL** from the `...` dropdown menu. 
:::

To use the PDF Viewer component:
1. Open the **Component tree** panel. 
2. Select the **+** to add a new component.
3. Select the PDF Viewer component and drag it to the app IDE. 
4. In the **Inspector**, select **Offline Asset** from the **PDF source** dropdown. 
5. Select the **Offline Asset** to view from the dropdown list. 

The PDF Viewer component displays the selected offline asset. 

export function ArcadeEmbed_pdfviewer() {
  return (
    
      
    
  )
}

---

## Offline mode

Offline mode makes it possible for Retool Mobile apps that run natively to continue functioning without a data connection. When enabled, queries that read data can cache the most recent results to make them available offline. Queries that write data are held in a queue and run once the data connection is restored.

## Considerations

If you plan to use offline mode, keep in mind the following considerations.

### Read queries only cache data when viewed by the user

Queries configured to read data for offline mode only cache data when the user views the results. The user must navigate to screens and view the query data at least once while connected.

If you need to download data in advance, consider using localStorage to temporarily download data that can be accessed when offline.

### Write queries run sequentially

Queries configured to write data in offline mode run sequentially when the connection is restored. If one query fails due to a conflict, the user must resolve it before any remaining queries can run.

### Write queries cannot have dependencies

Queries with pending changes in offline mode cannot depend on any other queries. For example, if you have a customer management app that is offline, the user could not create a new customer record and then refresh the list of customers. Similarly, the user could not create a new customer record offline and then make further changes.

### Handle conflicts

All pending tasks run sequentially when a device's connection is restored. If multiple users made changes to the same data, offline mode cannot merge their changes. Consider using sync delay when enabling offline mode so that users must trigger pending tasks.

### Cached data limits

Retool Mobile can cache up to 100MB of data. If offline mode exceeds this limit, Retool Mobile excludes the last used entries.

## Enable offline mode

Offline mode is available on a per-app basis and enabled in the app IDE. Click `•••` to open the **App actions** menu, select **Mobile app settings**, then toggle **Mobile offline mode** on.

Retool Mobile attempts to trigger pending queries automatically. You can require users to manually trigger pending queries that write data by toggling **Mobile offline mode delay sync**.

When offline mode is enabled, your app displays a connection status bar at the top of each screen.

- **Connected** or **Reconnected** (green): The app is connected to Retool.
- **Offline** (amber): The app is not connected to Retool and is operating in offline mode. The status includes the number of pending changes.
- **An error has occurred** (red): The app is unable to reconnect or cannot perform pending changes.

Retool Mobile stores cached data in the filesystem and is not lost when the app or device is restarted. Cached data is deleted if the app is uninstalled.

## Configure offline query types

You must configure the **Query type** for each query that should be available in offline mode:

- **Read**: The query reads data. The app caches the most recent data returned by the query and makes it available offline.
- **Write**: The query writes data. The app enqueues these queries and triggers them when the connection is restored.

Select a query in the bottom panel, navigate to the **Advanced** tab, and specify the **Query type** in the **Offline** section.

## View query status

The **Job Manager** contains a list of failed, pending, and completed queries. Tap the connection status bar at the top of the app screen to open it. Each entry contains the query name and date. Users can remove pending queries by pressing **Remove**.

Offline write queries can display key-value pairs in the Job Manager. You configure these using the **Display body** fields in the **Offline** section for a query.

Display body values can help provide context on the pending changes, such as displaying the original and modified values.

## Run pending changes

Retool Mobile automatically processes pending queries once the connection is restored. If **Mobile offline mode delay sync** is enabled, the Job Manager includes an action button to manually trigger the queries—users must press this for changes to occur.

The Job Manager processes each pending change sequentially. If a query fails for any reason, such as a conflict in data, the user must resolve this by retrying or removing the failed change. Any remaining queries will remain in a pending state until this is completed.

## Use Retool Storage in offline mode

Some users experience issues handling images in offline mode, because dependent queries are not supported after uploads. As a result, it’s impossible to execute post-upload processes while offline.

If you are having issues handling images in offline mode, reach out to your account manager or the support team and request that they enable the `mobileRetoolStorageAsync` feature flag.

This feature enables uploaded files to be stored on the device and added to the offline queue for later submission while providing the Retool Storage metadata right away. Users can then proceed with post-data processing even while offline.

---

## Reference dates and times in components

You can reference a configured date and time in various components, preserving the user's selected time zone.

import Components from '/docs/_shared/_dates-in-components.mdx';

---

## Display icons

import Shared from '/docs/_shared/_icons.mdx';

---

## Presentation and styling



---

## Share data between mobile app screens

Mobile apps use global and per-screen scopes for components and code.

- Globally scoped objects can be referenced across multiple screens. Retool continually evaluates globally scoped objects regardless of the screen currently in view.
- Screen-scoped objects can only be referenced within the same screen. Retool only evaluates screen-scoped objects when the screen is currently being viewed.

If you need to share data between screens, you can use globally scoped variables or localStorage.

## Share data using global variables

[Variables](../../queries/guides/store-temporary-data.mdx) temporarily store data for the duration of the user's app session. They can also include an optional initial value. 

To create a global variable, navigate to the Code tab and click **+ > Variable**. As the variable is globally scoped, you can update its value from any screen using [event handlers](./interaction-navigation/event-handlers.mdx), or with the `setIn()` and `setValue()` [JavaScript methods](../../queries/reference/objects/variable.mdx#methods).

Store data in a global variable.

You can then reference the global variable from any screen.

 
Reference a global variable.

For example, you can use the Table component's **Double Click Row** event handler to store the selected row data in a global variable. You can then reference the global variable in another screen, such as a component value.

If a user closes the tab, navigates away from the app, or opens the app in another tab, the variable reverts to its initial value.

## Store screen data in localStorage

:::warning

localStorage does not encrypt data. Only use localStorage to store nonsensitive information. 

:::

[localStorage](../../queries/guides/store-temporary-data.mdx) temporarily stores data in the browser's localStorage. Unlike variables, localStorage is a persistent data store. Provided the user continues to use the same browser and has not cleared their browsing history or cache, data remains available.

Use [event handlers](./interaction-navigation/event-handlers.mdx) or the `setValue()` [JavaScript method](../../queries/reference/objects/localstorage.mdx#methods) to store data in localStorage. You can also clear app-specific data using `clear()`.

---

## Mobile apps how-to guides

import Howto from '/docs/_partials/_doctypes/_howto.mdx';

:::tip Get started with mobile apps

If you are unfamiliar with Retool mobile apps and want to get started: 

- Read the [quickstart](./quickstart) to learn about the fundamental concepts.
- Follow a [tutorial](./tutorial/) to build your first mobile app.

:::

---

## Retool Mobile documentation

[Retool Mobile](https://retool.com/products/mobile) is a fast, complete solution for building native iOS and Android apps for your mobile workforce. Connect to your databases and APIs, assemble polished mobile interfaces with multi-page navigation, and deploy apps instantly.

---

## Retool Mobile quickstart

import Image from '@site/src/components/Image';

This guide serves as an introduction to Retool mobile apps that run natively on iOS and Android. It covers many of the concepts and terminology you would come across as you build mobile apps. After reading this page, you should have a good understanding of the fundamentals for building Retool mobile apps.

## Assemble the interface

A Retool Mobile app's user interface is comprised of screens and components. These interface elements function as objects with internal state.

- [Screens](#screens) are separate sections that contain their own code and components. Users navigate between screens, which are often used for distinct use cases. For example, a customer support app might have separate screens to view a list of customers and details of a selected customer.
- [Components](#components) are interface elements, such as a [text input field](./reference/components/forms/text-input.mdx) or a [button](./reference/components/buttons/button.mdx), with which users interact.

:::info

Retool Mobile app screens function in much the same way as [pages](../apps/quickstart.mdx) in Retool apps.

:::

Retool exposes properties, methods, and events with which you can interact. As you interact with components, their properties change. For example, entering text into a Text Input component changes its `value` property value.

You also write code that interacts with data, transforms values, or control behavior using JavaScript methods. For example, use `setValue('Jenny Appleseed')` to set the `value` property value of a Text Input component to **Jenny Appleseed**.

### Components

You build mobile apps using the [app IDE](../apps/concepts/ide.mdx) for Retool Mobile, Retool's drag-and-drop app building web interface. You use the app IDE to:

- Visually assemble the mobile app interface.
- Write queries to interact with data.
- Configure actions based on user interactions.
- Share apps directly with users.

### Screens

Retool only evaluates a screen's objects when the screen is currently in view. This allows for apps to serve multiple functions without impacting performance.

The **Screens** tab contains a list of screens within the app. The default screen is the one that first loads when launching the app. You can explore and manage all screens, change the default screen, and view more details.

Screens also function as modals and sheets, providing a number of ways for which users can interact. You can optionally configure screens with _actions_—buttons in the top bar that trigger event handlers

### Tab bar

The _tab bar_ is the primary navigation element in mobile apps. You specify which screens to include and they appear as selectable tab items. You can also customize the tab item's label and icon. Users then tap to navigate to each screen.

### Global and screen scopes

Apps use global and per-screen scopes for components and code.

- Globally scoped objects can be referenced across multiple screens. Retool continually evaluates globally scoped objects regardless of the screen currently in view.
- Screen-scoped objects can only be referenced within the same screen. Retool only evaluates screen-scoped objects when the screen is currently being viewed.

#### Globally scoped objects

You can create **Global** code (e.g., resource queries or variables), which all screens can reference. Each screen can interact with globally scoped code to trigger queries, set variable values, etc. For example, if you were building a customer support app then you could use a single globally scoped query to retrieve customer information rather than duplicate the same query across multiple screens.

You can drag code to either **Global** or **Screen** to change its scope. You can also move code across screens using the **Move to screen** contextual menu action.

All screens and their contents can reference globally scoped objects. Globally scoped objects, however, can only reference other globally scoped objects. For instance, a globally scoped query cannot reference a property for a component in a screen.

#### Screen-scoped objects

All code and components within a screen are screen-scoped, and cannot be referenced by other screens. If a screen contains code or event handlers that would run on load, these run whenever you navigate to the screen.

Globally scoped and screen-scoped code and components.

## Connect interface elements together

Most component properties are editable. You configure them in the IDE with either static values (`string`, `number`, `boolean`, `array`, and `object`) or reference other component values using `{{ }}` embedded expressions, similar to the use of [template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals).

You reference property values using [dot notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_accessors#dot_notation). For instance, you can select an item from the inventory list to get more details. The Image component value is set to `{{ itemCollection.selectedItem.image }}`, which updates whenever you change the selection.

## Use JavaScript expressions for values

Retool performs [string interpolation](https://en.wikipedia.org/wiki/String_interpolation) and evaluates `{{ }}` embedded expressions as JavaScript. As a result, you can write JavaScript code—that evaluates and returns a value synchronously—almost anywhere. This enables you to dynamically set property values using transformations or conditional logic to build complex apps.

The List Collection component uses a ternary operator and the selected value of the Segmented Control mobile component to toggle sorting the list by quantity or price.

```js
{{
  sortOptions.value === 'quantity'
  ? getItems.data.sort((a, b) => b.quantity - a.quantity)
  : getItems.data.sort((a, b) => b.price - a.price)
}}
```

## Connect your data using resources

A resource is a saved set of user-configured properties that determines how Retool connects to a data source, such as a [PostgreSQL](../data-sources/guides/integrations/database/postgresql.mdx) database or [REST API](../data-sources/guides/integrations/api/rest.mdx). You create a resource for each data source you want to use with Retool, then write queries to interact with them.

Each resource has configuration options that Retool uses when interacting with a data source. This simplifies how you query data sources while ensuring access is secure.

import Lifecycle from '../_partials/_resource-lifecycle.mdx';

## Read and write data using queries

A query is a piece of code you write to interact with a resource and perform CRUD operations. As with components, queries maintain an internal state and expose properties. Queries can also perform asynchronous actions and run simultaneously with other queries.

Queries are not part of an app's user interface. You reference the query's `data` property to read and display data in components for which users can interact. Queries can also reference component input values and write them back to the data source.

## Connect the interface together

Under the hood, Retool maintains a dependency graph for each app. This represents all property values and where they're referenced. Whenever a property changes, all downstream references using embedded expressions automatically update. This is similar to how spreadsheet formulas work when referencing cell values; if a referenced value changes then the formula instantly updates its result.

The **Component tree** and **Code** panels contain the **Graph** pane. This visualizes the dependency graph for a selected component or query. You can use the graph to view the relationship between the selected component or query and its immediate dependents.

export function ArcadeGraph() {
  return (
    
      
    
  )
}

:::tip

Hover the cursor over the connecting points to display a tooltip with a list of dependencies and dependents.

:::

You can chain embedded expressions together by referencing values that also use embedded expressions. Any input value changes automatically propagate through the entire app. This makes it possible to build powerful applications with very few lines of code.

:::info Dependency cycles
The dependency graph enables Retool to prevent you from creating circular dependencies, where two or more properties rely on each other to function. If you attempt to reference values that rely on one another, the IDE displays a warning.

:::

The Inventory mobile app contains a List Collection component to display a list of inventory items. Its data source is set to `getItems.data`. There is also a slider that filter results based on quantity. This is done using a JavaScript `filter()` expression that transform the output of the query.

```javascript
return formatDataAsArray(data).filter(row => row.quantity 

## Control and run queries with event handlers

You configure event handlers to perform actions whenever a specific event occurs, such as a button press or query error. There are numerous actions available, such as setting component values and triggering queries.

The Inventory mobile app uses a number of different event handlers. For instance, an event handler is configured to navigate to the `itemDetailsScreen` screen when an item is selected from the list. This screen contains components that reference the selected item's properties.

## Transform data using transformers

While you can use JavaScript within `{{ }}` embedded expressions, you may need to manipulate multiple sources of data and implement complex logic to produce values, such as filtering or joining data sets.

A [transformer](../queries/guides/transformers.mdx) is a reusable block of JavaScript. Unlike the data transformation you can perform directly from a query, transformers operate independently. You reference property values using embedded expressions and the results of the transformation are output on the transformer's `value` property using a `return` statement.

The Inventory mobile app uses a transformer, `totalPrice`, to calculate the total amount of all visible items. The result is then formatted using `toLocaleString()` and displayed in a Text mobile component.

```js
const items = {{ getItems.data }}
const total = items.reduce((acc, item) => acc + (item.price * item.quantity), 0);

const formattedTotal = total.toLocaleString('en-US', {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
});

return formattedTotal;
```

Transformers are maintained by the dependency graph and continually output a transformed value. If you make changes to any values in the dependency chain, the transformer automatically updates.

## Script apps with JavaScript

You can write JavaScript code to control app behavior, set property values, and more. Components and queries are globally scoped and include built-in methods to control their state. These methods can accept supported parameters, such as string or index values. In either case, you only need to use standard JavaScript notation, not `{{ }}` embedded expressions.

:::note JavaScript output
JavaScript queries can output data using a `return` statement.
:::

The **Reset** button below the list triggers a JavaScript query that sets the value of the Slider and Segmented Control mobile components, effectively resetting the results to their defaults.

```js
quantitySlider.setValue(50);
sortOptions.setValue('quantity');
```

## Run apps natively on iOS and Android

:::tip Mobile PWA apps

You can run mobile apps in the browser as progressive web apps.

:::

Users browse and run mobile apps natively using the Retool Mobile app iOS and Android. This approach simplifies deployment and makes all Retool Mobile apps instantly available. You can share links to apps so users can launch them on their device, or open them in a browser.

The Retool Mobile app for iOS and Android uses [React Native](http://react-native.org/) to run mobile apps natively. Users can log in to their Retool organization, browse or search for mobile apps, and launch them on their mobile device.

Whenever you add or update an app, it's immediately available within the Retool Mobile app for users.

## Leverage mobile device functionality

Retool Mobile enables you to make use of the software and hardware functionality of mobile devices.

- **Biometric verification**. Use built-in biometric features to provide an extra layer of identity verification, such as fingerprint or face scanning. After users log in, they are prompted to verify their identity using biometrics each time they bring the app to the foreground. Biometric verification does not replace your existing login mechanisms.
- **NFC**: Use a device's built-in NFC reader to capture data from NDEF-formatted tags.
- **Camera**: Use the camera to take photos and scan barcodes.
- **Zebra**: Receive data captured by a Zebra Android device with dedicated hardware.

## Send push notifications

The Retool Mobile app includes support for push notifications. You can trigger notifications with queries using the built-in **Mobile Push Notifications** resource from any app or workflow.

Configuring push notifications is a two-part process:

- Add a query to mobile apps that subscribe users to push notifications and enables them on their device.
- Write queries in Retool apps and workflows to send push notifications to subscribed users.

Push notifications use topics to represent the scope for recipients. Topics are similar in function to mailing lists—users subscribe to them based on what information they want to be notified about. Users [subscribe to push notifications](./guides/app-management/push-notifications.mdx#subscribe-users-to-push-notifications) using a subscription query in which you specify the topics to use. To send a notification, you use a query that references the relevant topic rather than managing a separate list of users.

## Work offline

[Offline mode](./guides/offline-functionality/offline-mode.mdx) allows natively run mobile apps to continue functioning without a data connection. When enabled, queries that read data can cache the most recent results to make them available offline. Queries that write data are held in a queue and run once the data connection is restored.

## Test and troubleshoot issues

You can use Retool's [Debug Tools](./concepts/debug-tools.mdx) to explore your Retool Mobile app, review errors, and debug issues during development. You can also use the Model browser in the left panel of the app IDE to explore all component and query properties.

Retool Mobile does not support interactions using the web console. This includes `console.log()` or running JavaScript using the **Console** tab of Debug Tools. Instead, you can use components to display output by setting their values (e.g., Text Area) or **Run JS Code** JavaScript queries to perform certain commands directly in the app IDE.

## Wrap up

Using these fundamental concepts, you can build complex mobile apps that:

- Contain polished user interfaces that can adapt to your needs.
- Dynamically reference values anywhere using dependency chains.
- Connect with almost any API and database to interact with your data.
- Perform actions using conditional logic in response to user events or script apps to control behavior.

## Next steps

You now have a basic understanding of how to build a Retool app. Check out the [mobile app tutorial](tutorial.mdx) to build a complete app from start to finish.

---

## The Button component for Retool Mobile

## Properties

## Methods

## Events

---

## The Fab component for Retool Mobile

Fab floats above other content and remains at a fixed position.

## Properties

## Methods

## Events

---

## Button components for Retool Mobile



---

## The Checkbox Group component for Retool Mobile

## Properties

## Methods

## Events

---

## The Checkbox component for Retool Mobile

## Properties

## Methods

## Events

---

## The Date Picker component for Retool Mobile

## Properties

## Methods

## Events

---

## The Date Time Picker component for Retool Mobile

## Properties

## Methods

## Events

---

## The File Input component for Retool Mobile

## Properties

## Methods

## Events

---

## The Form component for Retool Mobile

## Properties

## Methods

## Events

---

## Form components for Retool Mobile



---

## The Multiselect component for Retool Mobile

## Properties

## Methods

## Events

---

## The Number Input component for Retool Mobile

## Properties

## Methods

## Events

---

## The Radio Group component for Retool Mobile

## Properties

## Methods

## Events

---

## The Search Bar component for Retool Mobile

## Properties

## Methods

## Events

---

## The Segmented Control component for Retool Mobile

## Properties

## Methods

## Events

---

## The Select component for Retool Mobile

Options are displayed in a full-screen list box with search filter when there are more than 10 values.

## Properties

## Methods

## Events

---

## The Signature component for Retool Mobile

## Properties

:::note

Retool recommends saving signatures with [utils.getDataByObjectURL()](../../../../queries/reference/libraries/utils.mdx#utilsgetdatabyobjecturl), which converts blobs into a Base64-encoded string. For more information, refer to the [Accept digital signatures](../../../guides/forms-inputs/signatures.mdx) guide. 

:::

## Methods

## Events

---

## The Slider component for Retool Mobile

## Properties

## Methods

## Events

---

## The Status component for Retool Mobile

## Properties

## Methods

## Events

---

## The Switch Group component for Retool Mobile

## Properties

## Methods

## Events

---

## The Switch component for Retool Mobile

## Properties

## Methods

## Events

---

## The Text Area component for Retool Mobile

## Properties

## Events

---

## The Text Input component for Retool Mobile

## Properties

## Methods

## Events

---

## Retool Mobile components reference



---

## The Card component for Retool Mobile

## Properties

## Methods

## Events

---

## The Collapsible Container component for Retool Mobile

## Properties

## Methods

## Events

---

## The Container component for Retool Mobile

## Properties

## Methods

## Events

---

## The Divider component for Retool Mobile

## Properties

## Methods

---

## Layout components for Retool Mobile



---

## The Spacer component for Retool Mobile

## Properties

## Methods

## Events

---

## The Tabbed Menu component for Retool Mobile

:::info Preset configuration

Tabbed Container is a preset configuration of the [Container](./container.mdx) and [Segmented Control](../forms/segmented-control.mdx) components. Refer to their documentation for more information about properties, methods, and events.

:::

---

## The Chart component for Retool Mobile

A chart to visualize data in different layouts using [Plotly](https://plotly.com/). Refer to [Plotly's JavaScript reference](https://plotly.com/javascript/reference/) to learn more about available options.

## Properties

## Methods

## Events

---

## The HTML component for Retool Mobile

:::note

The HTML component utilizes [react-native-render-html](https://github.com/meliorence/react-native-render-html), and it has certain [limitations](https://github.com/meliorence/react-native-render-html/blob/master/HELP.adoc#standard) that mean it cannot always adhere to CSS or HTML standards.

:::

## Properties

## Methods

## Events

---

## The Icon component for Retool Mobile

## Properties

## Methods

## Events

---

## The Image Input component for Retool Mobile

Captured images are temporarily stored on the device for native apps and in the Retool organization for web apps.

## Properties

## Methods

## Events

---

## The Image component for Retool Mobile

## Properties

## Methods

## Events

---

## Media components for Retool Mobile



---

## The Map component for Retool Mobile

An embedded map using [MapBox](https://www.mapbox.com/) to display latitude and longitude coordinates as points of interest. It supports default coordinates and can trigger queries when selecting a point.

## Properties

## Methods

## Events

---

## The Microphone component for Retool Mobile

Recordings are Base64-encoded in WebM format, and audio playback displays a progress bar and elapsed time.

## Properties

## Methods

## Events

---

## The NFC Reader component for Retool Mobile

NFC Reader supports reading NDEF-formatted tags. Please [reach out](mailto:mobile-team@retool.com) if your use case requires reading other NFC formats.

## Properties

## Methods

## Events

---

## PDF Viewer component

## Properties

---

## The ProGlove component for Retool Mobile

Receive data captured by an Android device with a connected [ProGlove scanner](../../../guides/hardware-integrations/proglove.mdx).

## Properties

## Methods

## Events

---

## The Scanner component for Retool Mobile

## Properties

## Methods

## Events

## Supported barcode formats

Mobile Scanner supports a range of barcode formats on iOS and Android.

| Name                        | Short name      |             iOS             |           Android           |
| :-------------------------- | :-------------- | :-------------------------: | :-------------------------: |
| Aztec Code                  | aztec           |   |   |
| Codabar                     | codabar         |   |   |
| Code 39                     | code39          |   |   |
| Code 39 with 43 check digit | code39mod43     |   |  |
| Code 93                     | code93          |   |   |
| Code 128                    | code128         |   |   |
| Data Matrix                 | datamatrix      |   |   |
| EAN-13                      | ean13           |   |   |
| EAN-8                       | ean8            |   |   |
| Interleaved 2 of 5          | interleaved2of5 |   |  |
| ITF-14                      | itf14           |   |   |
| MaxiCode                    | maxicode        |  |   |
| PDF417                      | pdf417          |   |   |
| RSS 14                      | rss14           |  |   |
| RSS Expanded                | rssexpanded     |  |   |
| UPC-A                       | upc_a           |  |   |
| UPC-E                       | upc_e           |   |   |
| UPC/EAN-13                  | upc_ean         |  |   |
| QR                          | qr              |   |   |

---

## The WebView component for Retool Mobile

## Properties

## Methods

## Events

---

## The Zebra DataWedge Reader component for Retool Mobile

Receive data captured by a Zebra Android device with dedicated hardware and sent using the [Zebra DataWedge APIs](https://techdocs.zebra.com/datawedge/11-3/guide/api/). Refer to the [Retool Mobile on Zebra devices](../../../guides/hardware-integrations/zebra/index.mdx) guide for instructions.

## Properties

## Methods

## Events

---

## The Card Collection component for Retool Mobile

## Properties

## Methods

## Events

---

## The Custom Collection component for Retool Mobile

## Properties

## Methods

## Events

---

## Pattern components for Retool Mobile



---

## The Key Value component for Retool Mobile

## Properties

## Methods

## Events

---

## The List Collection mobile layout

## Properties

## Methods

## Events

---

## The Heading component for Retool Mobile

## Properties

## Methods

---

## Text components for Retool Mobile

Mobile components to display headings and plain text.

---

## The Text component for Retool Mobile

## Properties

## Methods

---

## Retool Mobile environment variables

import Mobile from "@site/docs/self-hosted/reference/environment-variables/mobile.mdx";

---

## Mobile app event handlers reference

## Events

Support for each event depends upon the component or object being configured.

## Actions

import Actions from '/docs/_shared/_event-handler-actions.mdx';

---

## Mobile apps glossary

import SharedGlossary from '../../_partials/_glossary.mdx';

---

## The Current User object

## Properties

---

## The Retool Context object

## Properties

---

## The Theme object

## Properties

---

## The Url object

## Properties

---

## The Viewport object

## Properties

---

## Retool Mobile reference

import Reference from '/docs/_partials/_doctypes/_reference.mdx';

:::tip Get started with web apps

If you are unfamiliar with Retool mobile apps and want to get started: 

- Read the [quickstart](./quickstart) to learn about the fundamental concepts.
- Follow a [tutorial](./tutorial/) to build your first mobile app.

:::

---

## Retool Mobile tutorial

[Retool Mobile](https://retool.com/products/mobile) enables you to quickly build mobile apps using a drag-and-drop interface and mobile component library. You can connect almost any database and API to Retool, allowing your workforce to interact with your data using native apps for iOS and Android.

This tutorial explains how to build a basic customer management mobile app on Retool. You can browse through a list of customers, select one to view details, and update their email address.

## Prerequisites

Familiarity with common technologies like APIs, SQL, and JavaScript is expected to complete this tutorial. If you need to learn more about these technologies, try the following online learning resources:

- [Freecodecamp: How to use REST APIs](https://www.freecodecamp.org/news/how-to-use-rest-api/)
- [Khan Academy: Introduction to SQL](https://www.khanacademy.org/computing/computer-programming/sql)
- [Codecademy: JavaScript](https://www.codecademy.com/catalog/language/javascript)

## What you'll learn

After completing this tutorial, you'll gain the necessary knowledge to:

- Connect your data sources as resources.
- Assemble user interfaces using drag-and-drop components.
- Query resources to interact with data.
- Connect queries and components to manipulate data.
- Extend your app's functionality with JavaScript queries and transformers.

These terms and concepts may not be familiar but you'll learn about them as you work through the tutorial.

## 1. Create a resource

Retool can interact with almost any API or database, and includes [native integrations](../data-sources/index.mdx) for many different data sources. After you configure a resource, you can build apps using your data.

Return to the **Resources** page and then navigate to the **Apps** page.

## 2. Create a new mobile app

Navigate to the Apps page and click **Create new > Mobile app**. Every new mobile app is initially configured with a demo that uses a preconfigured interface and sample data for you to try out. For the purposes of this tutorial, remove the demo content when you open the app.

export function CreateNewApp() {
  return (
    
      
    
  )
}

When you develop a Retool Mobile app, the [Mobile IDE](../apps/concepts/ide.mdx) renders your mobile app on the canvas. On the left are tabs that contain sections to manage different aspects of the app, such as Screens and Components. When you select a screen or component, the Inspector on the right provides you with configurable settings.

## 3. Prepare screens

You create multi-screen mobile apps where each [screen](guides/interaction-navigation/screens.mdx) functions as a separate _page_ with its own code and components. You can navigate between each screen using the tab bar or by interactions that trigger event handlers, such as pressing a button or selecting an item from a list. Retool only evaluates the code and components of the screen currently in view, ensuring that complex mobile apps are performant.

### Add new screens

This app uses two screens, one for displaying a list of customers and another for editing the selected customer's details. To add these screens:

1. Navigate to the Screens tab and click .
2. Right-click the screen and select **Rename**, then set its name to `customers`. 
3. Repeat the process to add a screen named `customerDetails`.

Once done, right-click the **customers** screen and select **Set as default screen**.

After adding the new screens, right-click on each existing screen and select **Delete**.

export function AddScreens() {
  return (
    
      
    
  )
}

Each screen has a title to identify which screen a user is currently viewing. This is displayed at the top of the app and in the navigation bar. Set the title for the **customers** and **customerDetails** screens by selecting one and updating the **Title** in the Inspector to `Customers` and `Customer details`, respectively.

## 4. Get customer data

You write [resource queries](../queries/tutorials/resource-query.mdx) to interact with resources, such as SQL statements or API requests. Queries can be either screen-scoped or globally scoped. For the purposes of this tutorial, add a page-scoped query:

1. Navigate to the Code tab.
1. In the **customers** section, below the **Global** section, click  and select **Resource query**.
1. Select the resource you created for the mock API.

When you select an API resource, the code editor contains a set of inputs for you to write an API request. APIs commonly use different endpoints based on the type of data used. You don't need to specify an endpoint to get customer data from the mock API. Since API queries default to using a **GET** request, no further configuration is needed. Click **Save & Run** to save the query and perform the API request. 

The query results appear below the code editor. The mock API returns a list of customer data that you will use to populate the mobile app's UI in the next step.

Before continuing, delete the demo queries that were included when you created the app. Right-click on each query and then select **Delete**.

export function GetCustomers() {
  return (
    
      
    
  )
}

## 5. Display a list of customers

The [List Collection](./reference/components/patterns/list-collection.mdx) mobile component presents data using a list layout. You can use List Collection to display customer data without needing to build any type of repeatable layout.

Switch to the **customers** screen and then navigate to the Component tree tab. Click  and then select the **List Collection** component. 

Retool [automatically maps the most recently run query's data](guides/forms-inputs/option-lists.mdx) to the component and populates values based on common usage (e.g., using `item.email` for an email address). Update the List Collection component's settings in the Inspector to the following:

| Setting | Value | Description |
| --- | --- | --- |
| Title | `{{ item.first }} {{ item.last }}` | Use the customer's name for the list item title. |
| Body | `{{ item.email }}` | Use the customer's email address for the list item body. |
| Media type | **None** | Since the customer data has no images, disable the list item image. |
| Action type | **Label and icon** | Display an optional label and icon on the right-side of the list item. |
| Label | Empty | Clear the label text to remove it. |

## 6. Add a customer search field

You can add a text input field that dynamically filters the list of customers, making it easier to find what you're looking for. The [Search Bar](./reference/components/forms/search-bar.mdx) mobile component is a preset of the Text Input mobile component, which is preconfigured with a search icon already. 

Add a **Search Bar** mobile component to the customers screen, then change its **Label** to `Search` from the Inspector.

Mobile components are arranged vertically by default. When you add the Search Bar component, it appears below the List Collection component. In the Component tree tab, click and drag the Search Bar component to position it above List Collection.

export function DisplayCustomers() {
  return (
    
      
    
  )
}

## 7. Filter the list of customers

To use the input value of Search Bar to search customers, you can use either client-side or server-side filtering. For the purposes of this tutorial, the app uses client-side filtering.

With client-side filtering, all necessary data is retrieved first and then filtering occurs within the app. You should use client-side filtering if:

- There is only a limited amount of data.
- The resource does support server-side filtering of data.

With server-side filtering, the query uses the filter value when making the request. The resource then returns only matching data. You should use server-side filtering if:

- There is a large amount of data.
- The resource supports server-side filtering of data. 

You can use `{{ }}` embedded expressions to write JavaScript almost anywhere in Retool. The mock API supports filtering with the `filter` URL query string, and you can reference the value of Search Bar directly in the query.

### Filter with a transformer

You can use a transformer to perform client-side filtering of query results. Transformers dynamically update whenever there is a change to reference values. 

To create a transformer:

1. Navigate to the Code tab.
2. Click  and select **Transformer**.

Next, write a JavaScript statement that filters the results based on the value of Search Bar using the `filter()` JavaScript method.

```js title="filterCustomers"
// Reference the customer data from the query
const data = {{  getCustomers.data }}

function filterCustomers(searchString) {
  // Search customers based on first + last names
  const filteredData = data.filter(customer => {
  // Combine the first and last names into a single, lowercase string
  const fullName = `${customer.first} ${customer.last}`.toLowerCase();
  return fullName.includes(searchString.toLowerCase());
});
// Return the results
return filteredData;
}

// use the filterCustomers function with the value of the Search Bar component
return filterCustomers({{ searchBar1.value }});
```

To use the transformer results, update the **Data source** of the List Collection component to use `filterCustomers`.

export function Transformer() {
  return (
    
      
    
  )
}

## 7. Select a customer and view details

This mobile app will allow users to view customer details. When a user selects a customer, the app navigates to the **Customer details** screen which will display customer information.

### Navigate to another screen

First, configure the app to show the **customerDetails** screen when selecting a customer. Retool uses [event handlers](guides/interaction-navigation/event-handlers.mdx) to trigger queries or other actions in response to user events, such as selecting a product.

Select `collectionView1` within the **customers** screen and add an event handler from the **Interaction** settings of the Inspector. Configure the event handler with the following settings:

| Setting    | Value            | Description                                                   |
| ---------- | ---------------- | ------------------------------------------------------------- |
| **Event**  | **Press**        | Trigger the specified action when the user selects a customer. |
| **Action** | **Navigation**   | Perform the specified navigation.                             |
| **Method** | **Navigate to screen**   | Navigate to the **customerDetails** screen.              |
| **Screen** | **customerDetails** | The screen that appears when the user selects a customer.      |

Click on a customer to test the event handler. The **customerDetails** screen doesn't contain any components and is currently empty. 

export function EventHandler() {
  return (
    
      
    
  )
}

### Store the selected customer data

Code and components are screen-scoped or globally scoped. Since the `getCustomers` query is scoped to the `customerDetails` screen, its cannot be referenced elsewhere. You use [variables](../queries/guides/store-temporary-data.mdx) that are globally scoped to tempoarily store data and make it available in other screens.

1. Navigate to the Code tab.
1. In the **Global** section, click  and select **Variable**.
1. Rename the variable to `selectedCustomer`. 

The List Collection component's `selectedItem` contains the data of a selected item, which is available at `{{ item }}` when configuring an event handler. Create another event handler to store this data in a variable.

| Setting    | Value            | Description                                                   |
| ---------- | ---------------- | ------------------------------------------------------------- |
| **Event**  | **Press**        | Trigger the specified action when the user selects a customer. |
| **Action** | **Set variable**   | Perform the specified navigation.                             |
| **State** | **selectedCustomer**   | The variable in which to store data.              |
| **Method** | **Set value** | Set a variable value when the event handler runs.      |
| **Value** | `{{ item }}` | The selected item. |

When you select a customer, the app loads the `customerDetails` screen.

export function GlobalVar() {
  return (
    
      
    
  )
}

### View selected customer data

`selectedCustomer.value` is an object with the selected customer data. To view this data:

1. Add a [Key Value](./reference/components/patterns/key-value.mdx) mobile component to the `customerDetails` screen.
1. In the Inspector, set **Data** to `{{ selectedCustomer.value }}` and **Header** to `{{ selectedCustomer.value.first }} {{ selectedCustomer.value.last }}`.

The selected customer data appears in the Key Value component automatically. Its header also displays the customer's name.

export function SelectedCustomer() {
  return (
    
      
    
  )
}

## 8. Update the customer's email address

Now that the app displays selected customer information, the next step is to make changes and save them back to the resource. For the purposes of this tutorial, the app enables you to modify the customer's email address.

1. Add a **Text Input** component to the `customerDetails` screen.
1. Set the **Default value** of the component to `{{ selectedCustomer.email }}` from the Inspector.

### Add a query to update the email address

The Text Input component automatically displays the email address of the selected customer. You add another resource query to save changes, similar to the query that retrieves customer data.

1. Add a **Resource query** to the `customerDetails` screen. This must be screen-scoped as globally scoped queries cannot reference any data from a page. 
1. Select the mock API resource.
1. Rename the query to `updateCustomer`. 

APIs commonly use `PATCH` or `PUT` methods to modify existing data. These request methods require the object's identifier (ID). This is also stored in `selectedCustomer`. Update the query with the following configuration:

| Setting | Value | Description |
| --- | --- | --- |
| Action | **PATCH** | Use the **PATCH** method to modify an existing object. |
| URL | `{{ selectedCustomer.value.id }}`. | This updates the API endpoint to use the customer ID (e.g., `https://example.com/customers/1`) that determines which object to update. |
| Body (key) | `email` | The property to update. |
| Body (value) | `{{ textInput1.value }}` | The value with which to update. |

Queries also support event handlers. Once a customer email address is updated, the app should return to the `customers` screen. Add an event handler with the following configuration:

| Setting    | Value            | Description                                                   |
| ---------- | ---------------- | ------------------------------------------------------------- |
| **Event**  | **Success**        | Trigger the specified action when the query successfully runs. |
| **Action** | **Navigation**   | Perform the specified navigation.                             |
| **Method** | **Back**   | Navigate back to the previous screen.              |

When the event handler runs, the app returns to the `customers` screen. The `getCustomers` query automatically refreshes so the customer list reflects the changes.

### Add a button to save changes

The final step is to add a button that saves the changes. 

1. Add a Button component to the `customerDetails` page.
1. Configure it with an event handler that uses the **Control query** action and select the `updateCustomer` query.

After you update email address and press the button to save changes, the following sequence occurs:

1. The `updateCustomer` query runs and updates the email address with `textInput1.value`.
1. After the query successfully runs, it triggers an event handler to navigate back to the `customers` screen.
1. Navigating back to the `customers` screen automatically triggers the `getCustomers` query, updating the customer data in the app.

export function EditDetails() {
  return (
    
      
    
  )
}

## Test your mobile app

Now that your app is complete, it's time to test it on your mobile device. Click **Go to app** in the top right to open the mobile app as a progressive web app (PWA). Scan the QR code with your iOS or Android device to launch it in the Retool Mobile app. You use this app to browse and launch any of the mobile apps you build.

If you don't have the app installed already, your device is automatically routed to the [iOS App Store](https://apps.apple.com/us/app/retool-mobile/id1586183808) or [Google Play](https://play.google.com/store/apps/details?id=com.retool.retool).

## Wrap up

You've now successfully built a mobile app that retrieves customer data and presents it in a list layout, and enables you to select a product and update its name.

---

## Branding

You can use branding to customize headers, sign up and login pages, email invites to users, the Retool user menu, and more. Navigate to your organization's [Branding](https://login.retool.com/auth/login?source=docs&redirectOnLogin=settings/branding) to configure.

To switch to a different page or email, use the dropdown menu on the right.

When customizing emails, to remove all references to Retool, you must enter a **From name** and a **Reply-to address**.

If you would like to provide support directly to your end-users, you can use the [custom Intercom support feature](../guides/external/intercom-messenger.mdx). This allows you to bring your own Intercom Messenger client to Retool.

Once set, branding is visible to anyone using your organization's apps in user mode.

:::note

You must be on the Enterprise plan to hide the Retool user menu. [Book a demo](https://retool.com/demo/?meeting_page_source=docs) to learn more about Enterprise functionality.

:::

---

## External users

Once you [enable external apps](../../apps/guides/app-management/external-apps/index.mdx), any authenticated user outside your organization is classified as an external user. All external users are added to a permission group, which enables you to control what apps they can access.

Common external users include customers, vendors, or partners. External users can only access [external apps](../../apps/concepts/share-externally/external.mdx) or [public](../../apps/guides/app-management/share.mdx#share-web-apps-with-users) links.

## Permission groups

Define internal users by email domain using the **External Apps** settings of your organization. Any user with an email that does not include this domain is categorized as an external user and added to the **External Users** [permission group](../../permissions/guides/configure-permission-groups.mdx). You can also create other permission groups and manage group membership to control the level of access external users have.

:::note

Prior to version 3.259.0, Retool's permissioning structure automatically granted the **All Users** group **Use all** access, which overrode any permission controls you set for the **External Users** group. Retool recommends [removing all access](../../permissions/guides/configure-permission-groups.mdx#configure-access-rules-for-a-permission-group) (**Edit**, **Use**, **Own**) from the **All Users** group and using the **External Users** group as the primary permission group.

For organizations created after version 3.259.0, the **All Users** group does not have universal access permissions by default. [Read more in the changelog entry](/changelog/updated-permissions-for-all-users).

:::

## Pricing

import External from '../_partials/_external-billing.mdx';

---

## Governance in Retool

Retool offers a powerful set of governance features that enable organizations to control, secure, and efficiently manage apps, workflows, and access to data. This guide explains ways to build a strong governance model in Retool, organized around the three levels of access management in Retool:

1. **Organizational access**: who is allowed to use Retool, and who is not?
2. **Project access**: within an organization, which Retool apps or workflows is a user allowed to use?
3. **Data access**: within a project, what data is a user allowed to view and update?

## Organizational access

Organizational access refers to how users in your company gain access to Retool. While an access approval process might happen outside of Retool (e.g., users request access in your company's ticketing system), Retool provides several ways to facilitate this access.

### Integrate with your identity provider

You can set up login, map groups, and provision users by integrating Retool with a [supported identity provider](../../sso/index.mdx) (IdP). Retool supports Google LDAP, and identity providers that support OpenID and SAML authorization protocols.

### User provisioning

Users can be provisioned into Retool directly through SSO, invitation, and access requests. Refer to the [user management](../tutorials/manage.mdx) tutorial.

If you want users to automatically be provisioned Retool accounts when visiting Retool's login page, you can set up [just-in-time provisioning](../../sso/guides/jit-provisioning.mdx). If the user exists in your identity provider but not yet in Retool, Retool automatically creates a user account and grants them organizational access. To make sure their access is scoped to the right project, you can map groups and roles directly to the custom groups you set up in Retool. See [Role-based access controls](#role-based-access-controls) for more.

### Spaces

Large organizations have many different teams and use cases that often operate independently. You can set up [Spaces](../tutorials/spaces.mdx) to enable isolation of teams and development workflows, without needing to create a separate Retool account if you're on cloud or spin up separate Retool instances if you're self-hosting.

In some cases, it may make sense to deploy several instances in separate VPCs to ensure network isolation between development and production instances. See [scale your Retool organization](scale-organization.mdx) for more.

### Programmatic management

Organizations on the Enterprise plan can programmatically create Spaces, set organizational settings, and configure SSO through the [Retool API](../../api/index.mdx). This allows you hook into your existing systems and centralize governance across your different teams using Retool.

## Project access

Project access refers to managing users' access to the different use cases–groups of apps, workflows, queries–you're using Retool for. For example, a project could be a suite of Retool apps built to allow your Support team to more easily work with data and update customer information. These are often organized in several folders in a given Retool organization or Space.

### Role-based access controls

Retool's role-based access controls let you manage access to Retool apps, folders, Workflows, resources, queries, and more. You can create multiple custom permission groups, assign access levels to Retool apps, and delegate [Group Admin](../../../permissions/guides/configure-permission-groups#custom-permission-groups) responsibility to users for them to manage group membership.

Users who do not have access to Retool apps cannot see them in the application listing.

[Learn more](../../permissions/quickstart.mdx#access-rules) about role-based access controls.

### Direct access sharing

Sometimes, it may be too much overhead for an admin to create a permission group to facilitate one-off access to Retool apps. When enabled, [direct access sharing](../../permissions/guides/app-permissions/share-apps.mdx) lets users with **Own** access to an app manage its permissions. You can audit access to an app and learn how access is granted—directly or from permission groups—from an app's access list in the application listing.

## Data access

Data access concerns a user's ability to see or edit sensitive data within Retool apps. In Retool, restricting access to apps displaying or working with sensitive data implicitly means restricting access to the data itself. Retool has controls to make sure editors and viewers can only see data they're allowed to see.

### Resource environments

Resource environments allow admins to configure resources that point to sensitive and nonsensitive data. Retool also supports setting permission groups' access levels to resource environments, which ensures that only certain groups can operate on production data.

[Learn more](../guides/configuration/environments.mdx) about resource environments.

### User attributes

Often, information about Retool users exists in systems outside of Retool, but is necessary to determine the data a user is allowed to access. User attributes allow you to set arbitrary metadata on the Retool user.

You can [reference user attributes](../guides/user-management/user-attributes.mdx) in Retool apps through JavaScript: you can hide and show data and app elements, as well as control custom behavior. You can also use them in queries, which makes it straightforward to set up [row-level security](../../queries/concepts/row-level-security.mdx) in Retool.

### Queries

To ensure users can only see data that is relevant to them, use [query spoofing prevention](../../queries/quickstart.mdx#query-variable-spoofing-prevention). This ensures that any query referencing attributes on the current user cannot be modified to return other data.

### Best practices

Many companies maintain access control services (in the form of APIs) that determine what data a user is allowed to see. Often these services rely on a user token sent from an identity provider upon login.

If you have OpenID SSO integrated with Retool, you can pass the JWT obtained from the login as a header to each request for this service. This ensures the Retool user is always authorized to make such requests, and your service would contain the necessary backend logic to determine what data to return to Retool.

If you don’t have OpenID SSO set up but have a separate authorization server, you can also define a [custom authentication workflow](../../data-sources/guides/authentication/custom.mdx#1-create-a-rest-api-resource). This lets your backend authenticate a user into your API.

## App development and release process

Retool also provides controls to manage app development, reviews, and releases to users.

### Source Control

[Source Control](../../source-control/index.mdx) allows organizations to manage changes to their Retool apps using pull requests on remote source control management (SCM) providers, such as GitHub and GitLab. Instead of making changes directly to an application, changes are made on a separate branch.

Protected apps are not modified until changes are reviewed and merged in the source control provider (e.g., in GitHub). This workflow mirrors a typical software development lifecycle, in which no engineer can push code directly to the `main` branch.

Source Control enables users to sync apps across multiple Retool instances and Spaces. If you have VPC isolation between non-production and production instances, a common approach is to configure your production instance of Retool as read-only, pulling changes from a central repository. Development happens on branches in a development instance, and once changes are reviewed through pull requests and app preview branches, code is merged into the main branch.

### Releases

[Releases](../../apps/guides/app-management/releases-history.mdx) let you version and release app changes to your users. This method can also be used in conjunction with Source Control. Once a branch is merged into production, you can review it on production data before rolling out changes to users using versioned release.

### Audit logs

On a Business or an Enterprise plan, Retool provides [audit logs](../guides/monitoring/audit-logs.mdx) for user actions that happen in Retool. If you're self-hosting Retool, you have access to the underlying PostgreSQL database on which your Retool instance runs. You can [connect it as a resource](../guides/monitoring/audit-logs.mdx#access-audit-logs-in-sql-or-stdout) and build your own Retool app to display custom views of your audit logs.

Additionally, you can send audit log events from Retool to DataDog. See our [guide](../guides/monitoring/audit-logs.mdx) for more details.
In self-hosted Retool, all audit logs stream to `stdout`, so you can set up an external service or sidecar that consumes them.

### Usage analytics

If you're on the Enterprise plan, [Usage Analytics](../guides/monitoring/usage-analytics.mdx) allows you to understand adoption across your organization at scale. By default for self-hosted Retool, usage is aggregated across all instances using the same license key. Similarly, if you have multiple Spaces set up on an instance, you can view usage across all Spaces.

---

## Internationalization

Retool supports internationalization (i18n), allowing you to adapt Retool app content and data for users across different languages and regions. This guide covers how to add translations to your Retool org and use Retool's out-of-the-box i18n functionality in your apps.

## Upload translations

Navigate to **Settings > Internationalization** to upload and manage your translations.

### File structure and naming convention

Your translation files should be structured as flat JSON objects and follow a consistent naming convention across different locales.

Below is an example of what your filesystem might look like. Each locale's directory (e.g., `en`, `es`, `fr`, `kr`) should contain the translation files with the same filenames (`common.json`, `customer_settings.json`). Make sure each file contains the same set of keys.

```
├── en
│   ├── common.json
│   └── customer_settings.json
├── es
│   ├── common.json
│   └── customer_settings.json
├── fr
│   ├── common.json
│   └── customer_settings.json
└── kr
    ├── common.json
    └── customer_settings.json
```

Here are example files for `common.json`, uploaded separately into Retool for the English (en) and Spanish (es) languages.

```json title="/en/common.json"
{
    "add_card_receipts": "add card receipts",
    "add_filter": "add filter",
    "amount": "amount",
    "budget": "budget",
    "date": "date"
    ...
}
```

```json title="/es/common.json"
{
    "add_card_receipts": "agregar recibos de tarjeta",
    "add_filter": "agregar filtro",
    "amount": "cantidad",
    "budget": "presupuesto",
    "date": "fecha"
    ...
}
```

### Upload translation files

Retool supports the most common ISO language codes, conforming to the ISO 639-1 standard, and includes country codes. Select your language and country code and upload your flat JSON file.

Files uploaded for locales without a country code specified will automatically be used as a fallback. For example, if a file is uploaded for `French (fr)`, translations will still work for users in France and Canada. If `French (fr-FR)` is also uploaded, then Retool will default to `French (fr-FR)` for users in France and `French (fr)` for users in Canada.

## Source Control

Retool supports the ability to sync translations across multiple spaces or instances by integrating with [source control](../../source-control/index.mdx). To get started:

1. Create a folder named `translations` at the root of your repository.
2. Inside this folder, use the same [file structure and naming conventions](#file-structure-and-naming-convention) that you use when uploading translation files directly to Retool.
3. All translation files in the `translations` folder are be automatically synced to Retool instances that are linked to the same source control repository.

## Localize your Retool apps

To localize your applications and format text, dates, and currencies, follow the [localization guide](../../apps/guides/app-management/localization.mdx). Retool provides default translations for strings in components in several languages.

---

## Provisioning and licensing

When you sign an annual agreement for the Enterprise plan on Retool, our team will assist with provisioning your purchased products and services. This depends on whether you use a cloud-hosted or self-hosted deployment.

## Cloud-hosted

For customers hosted in our multi-tenant Cloud instance, you will sign up for a new instance of Retool or utilize an existing instance of Retool on a self-service plan. Your Retool Account Executive will provision that instance of Retool with the required permissions to enable Enterprise plan features.

## Cloud-hosted and Retool-managed

For customers where Retool is managing your deployment inside of your own dedicated single-tenant infrastructure, Retool will manage all aspects of the licensing and provisioning process. Our infrastructure team will reach out to you with access instructions once your instance is deployed.

## Self-hosted

For customers who elect to self-host Retool in their own instance, your Account Executive will provide you with a unique license key via email that you will provide inside an environment variable for each deployment. This license key will expire at the conclusion of your Retool agreement’s service term, but the expiration date will be extended as and when your Retool agreement renews.

---

## Scale

This guide provides administrative best practices to scale your Retool use across your organization.

## Prerequisites

Before you begin, read about [governance in Retool](governance.mdx) and how to put the right controls in place to allow new teams to efficiently and safely use Retool. If you're self-hosting Retool, you should also understand Retool's [deployment model](../../self-hosted/guides/scale-retool-infra.mdx) and how it can be scaled to support new use cases in Retool.

## Set up a hub and spoke model

The hub and spoke model is an organizational model that can set up your teams to implement and scale Retool effectively. Under this model, a centralized group of platform administrators manage Retool and:

- Configure organizational setup like [Spaces](../tutorials/spaces.mdx), [SSO](../../sso/index.mdx) and [Source Control](../../source-control/index.mdx)
- Delegate permissions and oversee organizational access
- Perform maintenance and upgrades
- Help onboard new teams and provide best practices for using Retool

After deploying Retool, the _hub_ is responsible for making sure that the _spokes_ can build and use apps efficiently. Setting up the Hub requires identifying key stakeholders to manage Retool at the infrastructure and application level. To ensure smooth onboarding at scale, it's best to define your processes upfront.

### Identify your Retool platform owners

Delegate ownership of Retool to those who can oversee the specific needs and requirements of each team. Platform owners are usually responsible for defining access processes, and centralizing information to help new teams get to value quickly.

### Identify your infrastructure owners

If you're self-hosting Retool or connecting to sensitive data, appoint infrastructure owners who understand the technical aspects of Retool, including deployment, maintenance, and scalability.

### Define your governance model

Establish a clear [governance model](governance.mdx) that outlines rules, policies, and procedures for Retool development and usage. This includes:

- Developing knowledge of various use cases for Retool
- Reviewing the data sources connected to Retool, and their level of sensitivity
- Users groups who will be building and using Retool Apps and Workflows
- How new users and teams will onboard onto Retool
- Auditing, observability, and usage tracking features

#### Integrate with your identity provider

We recommend integrating Retool with an existing identity provider if you need to provision and manage many groups of stakeholders. With [just-in-time (JIT) user provisioning](../../sso/guides/jit-provisioning.mdx) enabled, users who exist in your identity provider are automatically provisioned Retool accounts upon signing into Retool.

As new teams and user groups are added, you can configure role-mapping between your identity provider and Retool as needed. New team members are automatically provisioned with Retool accounts (via [SCIM](../../sso/guides/scim-user-provisioning.mdx) or [Group Push](../../sso/guides/scim-user-provisioning.mdx#enable-group-push)), streamlining the onboarding process.

## Set up automations

Use the [Retool API](../guides/retool-api/index.mdx) to automate the creation and provisioning of new users, permission groups, and Spaces for new use cases.

## Define your development process

At scale and in production, having the right Retool app development process helps ensure a stable product for users. [Source Control](../../source-control/index.mdx) and [Releases](../../apps/guides/app-management/releases-history.mdx) are two key features to enforce a development lifecycle that scales across your company.

If you're using [Spaces](../tutorials/spaces.mdx), multiple teams can each have separate development workflows between development and production instances. See [Spaces and multiple instances](#spaces-and-multiple-instances) below.

### Set up Source Control

[Source Control](../../source-control/index.mdx) allows organizations to manage changes to their Retool applications using pull requests on remote source control management (SCM) providers, such as GitHub and GitLab. Instead of making changes directly to an application, changes are made on a separate branch.

Source Control enables users to sync applications across multiple instances of Retool. A common approach is to have staging and production instances of Retool be configured as read-only, pulling changes from the staging and main branches. All development happens via branches in a development instance and code is merged into the main branch. See our [recommended workflow](../../source-control/quickstart.mdx) for using Source Control in Retool.

### Reviews and ownership

Using the hub-and-spoke model, the hub typically configures a standard Source Control setup across Retool instances, as well as the Spaces within them.

With Spaces, you can copy Source Control setup from your admin Space to a child space, making it easy to standardize development across teams. If teams have their own flows, you can also delegate administrative privileges to other users within a Space, and they can set up Source Control for their Spaces as well.

When the hub has configured the required access controls and permissions, it should not be heavily involved in the day-to-day development of apps, but may coordinate releases to production.

### Versions and Releases

[Releases](../../apps/guides/app-management/releases-history.mdx) lets you version and release app changes to your users. This method can also be used in conjunction with Source Control.

Although you can configure your application to use the `main` branch, you may still not want it to update every time the branch is updated. In these cases, you can create versioned releases and control when updates are available to your users.

### Codify onboarding and best practices

As you're setting up Retool, it's important that teams can quickly onboard onto Retool and deliver value for users. It's useful to create an organization-specific onboarding guide on the following topics:

- Overview of the organizational structure of teams who own and build in Retool
- How to identify a Retool use case
- How to obtain a Retool account
- How to obtain access to resources for your use case (APIs, databases, and permissions)
- Useful resources and documentation on development (pointing to Retool documentation)
- Application promotion and release process
- How to help onboard operations teams
- How to build Retool apps (e.g., video of using the App editor to build a new app)

You can use the [technical onboarding template](https://docs.google.com/document/d/1YDzNbT4mCAniA2NLOJTFkeGluhZ4Gdxxt8ZNp0YXXBY/edit?usp=sharing) to get started.

### Reuse groups of components with modules

You can use [modules](../../apps/guides/layout-structure/modules.mdx) to share groups of components across Retool apps. This encourages code reuse and delivers a more consistent end-user experience across your apps. Changes to a module are immediately reflected across all apps in which it is used. Modules also let you specify [inputs](../../apps/guides/layout-structure/modules.mdx#add-inputs) and [outputs](../../apps/guides/layout-structure/modules.mdx#add-outputs), allowing you to centralize and reuse logic across different use cases.

### Reuse queries

The [Query Library](../../queries/concepts/query-library.mdx) enables you do create and reuse queries in the same way as modules function to reuse components. You can write, share, and control access to queries from the Query Library, which is important if you have many apps leveraging the same data source.

Any queries in individual apps should be moved into the Query Library if you find the same queries being written across apps. Queries within the Query Library also have permissions, so if you have complex or sensitive queries and want a specific team to own them, you can manage access through your organization settings.

### Customize style with themes

You can create themes with custom color palettes that can be quickly applied to apps. [Themes](../../apps/guides/presentation-styling/themes.mdx) provide a way for builders to build apps that match their organization's existing brand guidelines.

## Scale Retool to new use cases

Because Retool can be applied to solve a broad range of use cases, when a new use case comes up, it's important to understand its nature: what data these apps or workflows are accessing, isolation considerations, and change management processes.

Depending on the above, you can choose a combination of deploying a new Retool instance, Spaces, and permission groups to ensure teams are onboarded quickly with the right processes in place.

### When to deploy a new Retool instance

If you're self-hosting Retool for data security or compliance reasons, you are likely running a [multi-instance deployment](../../self-hosted/concepts/multi-instance-deployment.mdx) with at least two instances, one representing a production and the other a non-production instance. If a new use case requires additional VPC isolation between production user groups due to sensitive data or isolated user pools, it's recommended you deploy an additional production instance.

You can set up [Source Control](../../source-control/index.mdx) to automatically sync and promote changes between instances and enable a Git-based review process for your application changes, as outlined above.

#### Spaces and multiple instances

:::warning

To use Spaces with Source Control, ensure you [migrate your apps to Toolscript](/changelog/yaml-serialization-deprecation).

:::

[Spaces](../tutorials/spaces.mdx) drastically reduces the administrative overhead of onboarding new, isolated groups of users. You won’t need to spin up additional instances to ensure full separation of apps, resources, and users. If you are using Spaces and Source Control, you can use the following approach:

1. **Create two additional child Spaces**. Create one on your new production instance, and another on your existing development instance. This keeps your development instance neat with no additional overhead.
2. **Connect Spaces to the same Git repository**. Copy settings through the UI or use the [Retool API](../guides/retool-api/automate-spaces.mdx) to programmatically configure Source Control on each Space.

### When to create a Space

Spaces provide access and isolation guarantees at the organizational level, while permission groups help you control project access. Spaces makes sense when the benefit of isolated development workflows and user groups outweighs the benefit of sharing.

For example, you might develop apps and workflows specific to your Sales organization to track account health, usage, and forecasted pipeline. These apps and workflows might be built on top of [Salesforce](../../queries/tutorials/examples/salesforce.mdx) and a data warehouse resource (e.g., [Databricks](../../data-sources/guides/integrations/analytics/databricks.mdx), [Snowflake](../../data-sources/guides/integrations/analytics/databricks.mdx), or [BigQuery](../../data-sources/guides/integrations/database/bigquery.mdx)). If your DevOps team has a new Retool use case and wants to build apps to manage their deployment configuration on top of RDS using AWS APIs, it makes sense to create a new Space for them. This lets them build, deploy, and use Retool apps while managing users in a completely isolated setting. Assuming the organizations can use the same Retool instance, you would create Spaces on the same instance: **sales.retool.mycorp.com** and **devops.retool.mycorp.com**.

In this context, a Retool platform owner could delegate administrative responsibility to admins of each respective Space, while reusing the same SSO configuration. Because resources, queries, and even development processes are so separate between teams, there is little benefit to keeping these two organizations within the same Space.

:::note

You can automate Space creation and configuration using the [Retool API](../guides/retool-api/automate-spaces.mdx).

:::

### When to use permission groups

In the above example, the Retool apps in **sales.retool.mycorp.com** could be used across Account Executives, Sales Operations, Sales Managers, and the leadership team. Depending on the size of the organization, certain teams and users within the Sales org could require privileged access to certain apps. In this case, creating permission groups per team is the recommended approach.

Keeping Sales-related use cases in the Sales Space allows you to more quickly build new applications:

- Resources, applications, and modules are already configured
- Teams have organizational context on which apps and queries are useful
- The development workflow is defined

Additionally, new users are more likely to find the applications that are relevant to them as they are provisioned into the Sales Space.

---

## Administration concept guides

import Concept from '/docs/_partials/_doctypes/_concept.mdx';

---

## Archive Retool Cloud users or organizations

Users on Retool Cloud organizations can archive their own accounts. Administrators can archive an organization, which also archives all users who belong to it. Archiving isn't supported for self-hosted deployments.

## Archive your user account

Archiving your user account disables your access to the Retool organization. You may want to archive your user account if you need to join a different Retool organization and want to use the same email address.

Administrators cannot archive individual users as this action must be performed by logging in as the user. To disable access for an individual user, administrators can [disable](../../tutorials/manage#disable-users) the account instead.

To archive your user account:

1. Navigate to the [Settings](https://login.retool.com/auth/login?source=docs&redirectOnLogin=settings) page.
2. Select **Account** in the sidebar.
3. Click **Archive account** at the bottom of the page.
4. Click **Archive account** on the confirmation modal.

You cannot archive your user account if you are the sole administrator of an organization. You must either promote another user to the **Admin** permissions group or archive the entire organization.

## Archive an organization

You must have **Admin** permissions to archive your organization. When you archive an organization, Retool also:

- Archives all users, which disables access for all users immediately.
- Disables active workflows and public apps.

If the organization is on a paid plan with a monthly subscription, archiving the organization cancels the subscription. If the organization is on an annual plan, archiving [does not result in a prorated refund](/support/billing-usage#annual-billing). Organizations with auto-join email domains configured will no longer be joinable by users with the listed email domains.

To archive an organization:

1. Navigate to the [Settings](https://login.retool.com/auth/login?source=docs&redirectOnLogin=settings) page.
2. Click **Advanced** in the sidebar.
3. Scroll to the bottom of the page and click **Archive organization**.
4. Click **Archive organization** on the confirmation modal.

---

## Change Retool Cloud subdomain

Retool Cloud admins can change an organization's subdomain at `retool.com` at any time. Performing this action permanently changes the URL of your organization (e.g., `acme.retool.com` -> `acme2.retool.com`).

:::warning Considerations when changing subdomain

Subdomain changes are permanent. Keep in mind the following considerations as you decide whether to make this change:

- **All organization URLs will change**. Any external references to your organization, such as bookmarks, must be updated to use the new subdomain. Any links that contain the previous subdomain will no longer work.
- **Previous subdomain will be released**. Once a subdomain is changed, the previous one is made available for other organizations to use.

:::

To change your subdomain, navigate to your organization's [Advanced](https://login.retool.com/auth/login?source=docs&redirectOnLogin=settings/advanced) settings. Specify the new subdomain to use and click **Save**. If the subdomain is not available, Retool suggests some alternatives. You can also enter another subdomain to check if it's available. 

Once the change is made, you are logged out and must log in again.

---

## Configure a custom domain for Retool Cloud

You can configure your Retool Cloud organization to use a custom domain. This enables your users to more easily navigate and improves the [embedded app](#using-retool-embed) across browsers.

## 1. Configure DNS

DNS configuration needs to be completed with the tooling you use to manage your top level domain name. This is often the registrar where you registered the domain, or a DNS provider such as Cloudflare or AWS.

Create a `CNAME` record mapping either the top level domain or subdomain to Retool’s alias for custom domains:

- `custom-domain.retool.com`

Retool recommends against using wildcard `*` DNS entries for your configuration as these can expose you to domain takeovers.

DNS changes can take up to 24 hours to propagate in some cases. To validate that your DNS is configured and propagated, you can use the `dig` command on the command line:

```
$ dig retool.example.com CNAME +noall +answer

; > DiG 9.10.6 > retool.example.com CNAME +noall +answer
;; global options: +cmd
retool.example.com. 120 IN CNAME custom-domain.retool.com.
```

## 2. Configure Retool

Navigate to `/settings/branding` in your organization's Retool settings. Under **Add a custom domain**, enter the domain name in the text box.

The domain briefly enters a pending state while Retool provisions HTTPS certificates and updates internal infrastructure to support the new domain. An error state likely indicates that the DNS wasn't updated to point to Retool. If this occurs, verify that your DNS is updated and that `dig` shows the correct IP addresses, and then retry verification.

## 3. Log in

The domain should be configured after a few minutes. Sign out of your organization and back in through your custom domain to confirm. Your new login page should be visible on `/auth/login`.

Note that you can still log in through `.retool.com/auth/login` as well as `/auth/login`.

:::info

The Sign in with Google option is not available by default when accessing the login page using your custom domain. You must configure [Google SSO](../../../sso/tutorials/google/google-sign-in.mdx) for your custom domain to make it available. Users can still log in using Sign in with Google at `.retool.com/auth/login` or `login.retool.com/auth/login` until you make this change.

:::

## Using Retool Embed

To [embed Retool apps](../../../apps/guides/app-management/embed-apps.mdx) from your Retool-hosted organization into a website like `https://example.com`, ensure that Retool is on the root `example.com` domain or a subdomain like `retool.example.com`. Because Retool is the hosting provider, you need to make some changes to your DNS configuration.

:::note

Some web browsers, like Safari, block third party cookies by default. Since Retool sets cookies when authenticating users, attempting to authenticate the embedded Retool app across domains is not possible in these browsers, unless you change your browser's cookie privacy settings.

:::

---

## Manage configuration variables

You can specify configuration variables for reference in resource configurations, apps, and workflows. Configuration variables are specific to resource environments and can be either values or secrets.

Retool encrypts configuration variables on Retool Cloud or, if you self-host Retool, in your deployment's PostgreSQL storage database.

## Requirements

Configuration variables are available on Retool Cloud and self-hosted Retool versions 3.4.0 and later for organizations on a Business or an Enterprise plan. Configuration variables in workflows are currently available on Retool Cloud.

You must be an admin to create and edit configuration variables. Configuration variable values and secrets availability depends on usage. Only users with **Edit** permissions for a relevant area (e.g., resources) can use configuration variables.

| Name      |                Values                |                Secrets                | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| --------- | :----------------------------------: | :-----------------------------------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Resources |  |   | Configuring resources in Retool can require handling sensitive values, e.g. database passwords or API keys. Retool is [SOC 2 Type 2 compliant](https://docs.retool.com/page/security), and most customers store these values with Retool. Configuration variables allow you to centralize and control access to these values. If you have specific security requirements that require you to store secret values externally, rather than encrypted in Retool’s database, consider integrating Retool with a Secrets Manager. |
| Apps      |  |  | Secret configuration variables are not available in apps and queries. You cannot use configuration variable values in [public or external](../../../apps/guides/app-management/embed-apps.mdx) apps.                                                                                                                                                                                                                                                                                                            |
| Workflows |  |   | As you build a workflow, Retool sanitizes secret configuration variables in block responses when running individual blocks. Secret values can only be passed to subsequent blocks when the workflow is run in its entirety, either by clicking **Run workflow** in the workflow IDE or when the workflow is triggered.                                                                                                                                                                                                       |
## Create configuration variables

To create a configuration variable, go to **Settings** > **Configuration variables**.

Configuration variables have resource environment-specific values. For example, if you create a `db_password` configuration variable, you may need to specify different values depending on the resource environment (e.g., production or staging).

### Secret configuration variables

To create a secret, toggle **Mark variable as secret** when creating a configuration variable. Secret configuration variables are available for use only in resource configurations and workflows, and their values are never exposed on the frontend. Use secrets if you need to store sensitive information, such as security credentials.

## Use configuration variables

You can use autocomplete to access configuration variables in the resource editor, app IDE, and workflow IDE. Retool uses the appropriate value depending on the current resource environment.

Reference configuration variables in resource configurations using the following syntax.

```
{{ environment.variables.YOUR_VAR_NAME }}
```

In apps, workflows, and queries:

```
{{ retoolContext.configVars.YOUR_VAR_NAME }}
```

:::info

Configuration variables are cached so it may take up to five minutes for your changes to take effect.

:::

## Configuration variables with multi-instance deployments

Config vars are recommended for use with [Protected Resources](../../../source-control/guides/protect/resources.mdx). When protecting a resource, only the template value (`{{ environment.variables.your_name }}`) is stored in Source Control. You must define your configuration variables on each instance.

## Configuration variables, environment variables, and Secrets Managers

The use of configuration variables, `RETOOL_EXPOSED` variables, and Secrets Manager depends on your security and permission requirements.

Config vars are set directly in the Retool settings web interface, are available on Retool Cloud and self-hosted Retool, and are stored encrypted. Use configuration variables when you need to access variables per resource environment.

On self-hosted Retool deployments, `RETOOL_EXPOSED_*` variables are set per-instance as [environment variables](../../../../self-hosted/reference/environment-variables/#retool_exposed_name). Their values are never exposed in Retool.

If your use case requires higher levels of security, integrating with a third-party Secrets Manager such as [AWS](../../../self-hosted/guides/secrets/aws.mdx) or [Vault](../../../self-hosted/guides/secrets/hashicorp-vault.mdx) is recommended.

## Configuration variables API

Organizations on the Enterprise plan running on Retool Cloud or self-hosted Retool versions 3.42 and later can use the [Retool API](../../../api/list-configuration-variables-and-their-values.api.mdx) to manage configuration variables.

---

## Configure resource environments

All Retool organizations on paid plans have _production_ and _staging_ resource environments:

- Production is the default resource environment for Retool apps and cannot be removed or renamed.
- Staging allows you to test apps without impacting production.

Administrators of Retool Cloud or self-hosted Retool organizations can create any number of separate resource environments to build, run, and test apps and workflows. All [administrators and editors](../../../permissions/guides.mdx#configure-access-rules-for-a-permission-group) can access and use these environments by default. Organizations on a Business or an Enterprise plan can configure [per-environment resource permissions](../../../permissions/guides/configure-permission-groups.mdx#control-access-to-resource-environments) to allow users to access only certain resource environments, such as allowing access to staging data but preventing access to production.

When you [configure a resource](#configure-environment-resources), you set the resource environments that resource is accessible in. This allows you to test apps with staging data and restrict access to production data. Resource environments differ from [versioning apps](../../../apps/guides/app-management/releases-history.mdx): apps function across resource environments. When you query a resource in an app, the resource's environments determine the data the app uses.

## Create a resource environment

Administrators create and manage resource environments for a Retool organization from the [Environments](https://login.retool.com/auth/login?source=docs&redirectOnLogin=settings/environments) settings. Click **Create new** to create a resource environment. All resource environments must have a unique name and display color.

## Configure resources

Multiple resources environments allow you to display and test against nonsensitive (non-production) data. You can set up connections to your data sources (e.g., database or API) and add environment-specific credentials within the same resource.

Each resource must be configured for your organization's default resource environment. New resources are configured for the default resource environment automatically.

To configure a resource for a specific environment:

1. Select the **Resources** tab and click **Edit**.
2. Add the appropriate resource credentials for each defined resource environment.

You don't need to configure a resource for every resource environment. Keep in mind that you cannot switch to an resource environment while editing an app if it hasn't been configured with a resource that is referenced by the app.

### Configure per-environment permissions

Admins for organizations on a Business or an Enterprise plan can configure different access levels to resources from **Settings > Permissions**. Learn more in the [permission groups documentation](../../../permissions/guides/configure-permission-groups.mdx#control-access-to-resource-environments).

## Switch resource environments

You can switch between resource environments directly from the app IDE. Users with edit or admin access can also switch resource environments in preview mode. You cannot switch to a resource environment that is not configured with a required resource.

You can access resource settings and configure them for other resource environments by clicking **Edit** in the **Resource** field of a query.

Switching resource environments automatically reloads the app to use the appropriate resources and credentials. If your resource requires authentication, users must re-authenticate the first time they switch to a different resource environment. Retool then stores separate access tokens for each resource environment.

### Viewer resource environments

Users that have **Use** access to an app can switch between multiple environments from the Retool contextual menu in the lower-left corner.

This feature is not supported on Retool Mobile.

## Use specific environments across apps

Retool saves your most recently selected resource environment to your browser cache and automatically uses it the next time you open an app. For example, if you switch to a staging environment in one app, the next app you open automatically uses the same staging environment.

You can link directly to a Retool app and include the `_environment` [URL query parameter](../../../apps/guides/app-management/customize-app-urls.mdx) to automatically open it with a specified environment.

:::note

The default resource environment for Public Apps is production.

:::

## Reference the selected resource environment

The `retoolContext` object contains the `environment` property that corresponds to the name of the resource environment currently in use. Use `{{ retoolContext.environment }}` to reference this anywhere you need to surface the resource environment in your app.

---

## Manage configuration

import DocCardList from "@theme/DocCardList";

---

## Manage users in your organization

import DocCardList from "@theme/DocCardList";

---

## Integrate Intercom Messenger for end-users

You can bring your own Intercom Messenger to Retool to provide support to end-users. End-users are shown a help bubble when viewing apps, and when clicked, your own Intercom Messenger is displayed.

## Requirements
To provide Intercom Messenger support to your end-users, your organization must be on a Business or an Enterprise plan. You must also be an admin of your organization to configure Intercom-related settings.

Retool requires that you use Intercom’s [Identity Verification](https://www.intercom.com/help/en/articles/7946878-what-is-identity-verification) feature. Intercom strongly recommend using this feature because it prevents user impersonation and ensures conversations are private.

## Set up Intercom Messenger support
1. Navigate to **Settings > Branding** in Retool.
2. Select **Configure** on the **Intercom Messenger Support** section.
3. Enter your **Intercom App ID**. See [Intercom’s documentation](https://www.intercom.com/help/en/articles/8771110-getting-started-faqs#h_8ebc4ba345) to find this value.
4. Enter your **Intercom Identity Verification Key**. This can be found in your [Intercom security settings](https://www.intercom.com/help/en/articles/183-set-up-identity-verification-for-web-and-mobile).
5. Click **Close** to save your changes.
6. Test the Intercom messenger client by navigating to a Retool app as a view-only user. Click the help bubble to reveal your Intercom messenger client.

## Sending user data to Intercom
Intercom allows organizations to track information about end-users through the use of both standard and custom data attributes. A user’s Intercom experience, including their Messenger client language, can also be customized using Intercom's data attributes.

By default, Retool sends only the following information about a user to Intercom:
* Email
* User SID

To send additional information about a user to Intercom, you must use Retool's [User Attributes](../user-management/user-attributes.mdx).

1. Navigate to **Settings > Branding** in Retool.
2. Select **Configure** in the **Intercom Messenger Support** section.
3. Under **User Attributes**, select **Add attribute** and select from one of your organization’s user attributes. 
4. Specify the name that the user attribute should be mapped to when it is sent to Intercom.
5. Click **Save**.
6. When an end-user next opens an app, the selected user attributes is sent to Intercom and can be seen under the **Details** section of the Intercom user.

---

## View user audit logs

:::warning

Audit logs require administrator [permissions](../../../permissions/quickstart.mdx).

:::

Retool automatically logs user actions, such as query runs and password resets. The logs include user information (such as the user ID in the audit log download, and the user's email on the **Audit logs** page), the action taken, and when the action took place.

You can access audit logs from either:

- The **User** menu on the top-right when browsing your organization.
- The **Retool** menu on the top-left of the app IDE.

To access the audit log, visit `/audit`. You can see a list of all the events that occurred, information about the user who performed them (email or user ID), and the time. You can also explore more detailed information, including the exact query, the parameters passed, the user's IP address, or response time. 

:::note
For a full list of events captured in the audit logs, refer to the [Logged events](../../reference/logged-events.mdx) reference page.
:::

Audit logs for Retool Cloud organizations are retained for one year. You can see the past three months of data using the **Date range** selector on the **Audit logs** page, and you can [download logs](#download-audit-logs-on-retool-cloud) for the past year. Self-hosted deployments manage their own audit log retention.

## Access audit logs in SQL

:::note

Access to the audit logs SQL table are only available on self-hosted deployments. If you're interested in a self-hosted deployment, [reach out](https://retool.com/demo/?meeting_page_source=docs) for a demo.

:::

Self-hosted Retool deployments can use SQL to query the audit logs database table.

### Query audit logs in SQL

Retool logs events to the `audit_trail_events` table in the [postgres](../../../self-hosted/concepts/architecture.mdx#postgres) database of the deployment instance. You can create a [PostgreSQL resource](../../../data-sources/guides/integrations/database/postgresql.mdx) if you want to build apps and workflows to query audit log data.

The `audit_trail_events` table contains the following columns.

| Column           | Description                                                                        |
| ---------------- | ---------------------------------------------------------------------------------- |
| `actionType`     | The type of action taken. See [Logged events](#logged-events) for possible values. |
| `userId`         | The ID of the user taking the action.                                              |
| `ipAddress`      | The IP address of the user taking the action.                                      |
| `responseTimeMs` | The response time of the action, in milliseconds.                                  |
| `pageName`       | The name of the app, module, workflow, or page on which the action was taken.      |
| `queryName`      | For query actions, the name of the query.                                          |
| `resourceName`   | For actions on resources, the name of the resource.                                |
| `metadata`       | Additional data about the action.                                                  |

You can join the `audit_trail_events` table with the `users` table to learn more details about the users who performed actions. For example, the following query returns records of groups created and the user who created each group.

```sql
select
u.email, u."userName", a."actionType", a.metadata
from
  audit_trail_events a
  join users u on a."userId" = u.id
  where a."actionType" = 'CREATE_GROUP';
```

## Export and download audit logs

If you self-host Retool, you can export and stream audit logs using SQL and `stdout` or by connecting to DataDog, which is supported on Retool Cloud as well.

### Output audit logs to stdout

If you self-host Retool, set the [environment variable](../../../self-hosted/reference/environment-variables/index.mdx#log_audit_events) `LOG_AUDIT_EVENTS=true` to output all audit log events to `stdout`. This is useful if you use external services to monitor and consume logs from `stdout`. You can set up a sidecar service that ingests these logs and set up custom monitoring in your APM solution.

### Stream audit logs to Datadog and Splunk

:::warning
This feature is only available on the Enterprise plan. If you self-host Retool, you must be running version 3.38 or later for Datadog and 3.114 or later for Splunk.
:::

To configure Datadog:

1. [Create a Datadog API key](https://docs.datadoghq.com/account_management/api-app-keys/) for streaming Retool audit logs.
2. Enter your Datadog API key on **Settings** > **Advanced** under **Audit Log**.

Logs will be sent to Datadog with `service:retool-audit-log` attribute.

To configure Splunk:

1. [Create an HTTP Event Collector (HEC) token](https://docs.splunk.com/Documentation/Splunk/9.3.2/Data/UsetheHTTPEventCollector) for Retool audit logs.
2. [Determine the HEC URI](https://docs.splunk.com/Documentation/Splunk/9.3.2/Data/UsetheHTTPEventCollector#Send_data_to_HTTP_Event_Collector) where the logs should be sent.
3. Enter your HEC token and URI on **Settings** > **Advanced** under **Audit Log**.

Retool sends logs to Splunk with `source:retool-audit-log` attribute.

### Download audit logs on Retool Cloud

Retool Cloud customers on a Business or an Enterprise plan can download audit logs directly from the Audit Logs page.

After selecting a date range and starting a download, the download job is displayed in a list with a **Pending** status. Once complete, a temporary link with a compressed CSV file is made available in the **Downloads** list. The link expires an hour after being created.

### Download audit logs on Self-hosted

If you self-host Retool and have connected to the Retool audit logs database table, you can export audit logs through the following SQL command:

```sql
\copy audit_trail_events to 'audit_logs' csv;
```

## Hide query data from logs

You can hide parameters from logs on a per-query basis. See the [query documentation](../../../queries/quickstart.mdx#hide-parameters-from-audit-logs) for more details.

To prevent all headers in queries from being logged, enable the `HIDE_ALL_HEADERS_IN_AUDIT_LOG_EVENTS` [environment variable](../../../self-hosted/reference/environment-variables#property-HIDE_ALL_HEADERS_IN_AUDIT_LOG_EVENTS). This is only available on self-hosted deployments.

---

## Monitor usage and logs

import DocCardList from "@theme/DocCardList";

---

## Monitor app and user analytics

As more users build and use Retool apps within your organization, it’s helpful to understand adoption patterns to better make decisions about your use of Retool. If you’re self-hosting Retool, you might run multiple instances, and seeing which users are using which apps can be difficult.

Retool provides a number of usage analytics for you to view that provide detailed information about users and app usage. For self-hosted organizations, usage analytics data is aggregated across all deployments that you have.

## View usage analytics

Admin users can view usage analytics for your organization by navigating to **Settings > Usage Analytics**.

Usage analytics are only available to admins by default. Admins can grant access to non-admin users using [permission groups](../../../permissions/guides/configure-permission-groups.mdx). Navigate to your permission group and under **Additional > Settings page visibility**, select **View usage analytics**. Users in this permission group can view organization-wide Retool usage.

Active users

The **Users** tab contains analytics for all users with access to your organization. This is segmented based on the following types:

| Type | Description |
| --- | --- |
| Total active users | Total number of all users in Retool in the previous 30-day window up to the selected end date. |
| Builders | Total number of distinct builders in the previous 30-day window up to the selected end date. |
| Internal users | Total number of distinct internal users in the previous 30-day window up to the selected end date. |
| External users | Total number of distinct external users in the previous 30-day window up to the selected end date. |

You can hover the cursor over each data point in the chart to view complete details for usage.

Users details

The **Users details** section provides more details about users. You can search the table to filter the results. Select a user in the table to view more details about their app usage over the specified time period.

Active apps

The **Apps** tab contains analytics for all app usage across the organization. This is segmented based on the following types:

| Type | Description |
| --- | --- |
| Total active apps | Total number of distinct apps viewed at least once in the previous 30-day window up to the selected end date. |
| Total app saves | Total number of app saves across all apps during the selected time period. |
| Total app views | Total number of app views across all apps during the selected time period. |

You can hover the cursor over each data point in the chart to view complete details for usage.

Apps details

The **Apps details** section provides more details about app usage. You can search the table to filter the results. Select an app in the table to view more details about its usage over the specified time period.

## Enable usage analytics for self-hosted Retool

Self-hosted organizations can enable Usage Analytics by setting the `USAGE_API_TOKEN` environment variable. This environment variable is a manually granted Usage Analytics access token to ensure security. To obtain this token, contact your Retool account manager.

If you self-host Retool, you might deploy multiple instances to isolate your production and non-production instances. Usage Analytics automatically gathers user and app usage (and other sensitive data) across all of your instances. Retool recommends enabling Usage Analytics on the instance with the most restrictions to keep data secure. Only admins of that instance will have the ability to view usage in **Settings > Usage Analytics** by default.

Retool assumes emails uniquely identify users. If a user is accessing multiple Retool instances, they must use the same email on each instance to avoid being counted multiple times in active-user counts. This also means that Retool expects to see a temporary spike in usage for an organization undergoing a domain migration.

---

## Configure Retool API authentication

The Retool API uses access tokens to authenticate requests. Organization admins can create access tokens from their organization's **Settings > API** page.

## Create an access token

import Tokens from "/docs/_partials/_tokens.mdx";

You can create access tokens in the **API** settings for your organization.

## Specify scopes and permissions

When you create an access token, you specify scopes that determine its level of access. Each scope has a set of permissions to control what operations are allowed when using the token.

Some scopes support individual read and write permissions. **Write** access also grants **Read** access.

import RetoolApi from "../_partials/_scopes/_retool-api.mdx"

## Authenticate requests

Authentication is performed using [Bearer HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#basic) with the provided token.

```shell
curl -X POST https://retool.example.com/api/v2/apps -H 'Authorization: Bearer $BEARER_TOKEN'
```

## Access tokens for spaces

If your organization uses [Spaces](../../tutorials/spaces.mdx), each space has its own authentication tokens and Retool API endpoints. With one exception, only tokens created for a space can be used to interact with its Retool API endpoints.

An admin can use a token from the primary organization to interact with Retool API endpoints for a space within the organization only when:

- The admin user created the token on the primary organization.
- The admin user of the primary organization is also an admin for the space.

## API rate limits

Retool uses a point system for rate limiting where endpoint requests cost a certain number of points. You can use up to 300 points in a 60 second window. If you exceed this, Retool blocks API calls for 60 seconds.

| Endpoints                                                                                                                                      | Points |
| ---------------------------------------------------------------------------------------------------------------------------------------------- | ------ |
| Apps, Folders, Users                                                                                                                           | 2      |
| Access Request, App Themes, Environment, Groups, Resources, Resource Configurations, Source Control, Spaces, SSO, User Attributes, User Invite | 5      |
| Permissions                                                                                                                                    | 10     |

## Create a Retool API resource

You can create a Retool API resource to interact with it using apps and workflows. Refer to the [Retool API resource guide](../../../data-sources/guides/integrations/api/retool-api.mdx) to connect using the OpenAPI integration.

---

## Automate user onboarding using the Retool API

To onboard teams to Retool, you often need to grant them the ability to build apps with new or existing resources. This can include:

- Creating app and resource folders
- Creating permission groups
- Setting folder permissions
- Provisioning users

Performing these tasks manually can be difficult to scale, but you can use the Retool API to automate these steps.

This guide outlines how to use the permissions and folder endpoints in the Retool API to onboard new users. If these users must operate in isolation from other teams, with their own resources, software development lifecycle, and release process, consider [creating a Space](automate-spaces.mdx) for them.

## Requirements

The [Retool API](../../../api/index.mdx) is available to cloud organizations and self-hosted organizations running v3.18 or later. API users must generate [access tokens](authentication.mdx) to authenticate. This guide assumes you have an access token with **Read and Write** scopes for users, permissions, and Spaces.

In this guide, replace `space-domain` with the domain of your [Space](../../tutorials/spaces.mdx) or organization, e.g., `organization.retool.dev` or `custom-space.organization.retool.dev`.

## 1. Create an app folder

The following command creates a top-level app folder named **Support**. The response contains the ID of the newly created folder; save this for a later step.

```shell
curl -X POST https://{space-domain}/api/v2/folders -H 'Authorization: Bearer $BEARER_TOKEN' -H 'Content-Type: application/json' --data '{"name": "Support", "parent_folder_id": null, "folder_type": "app"}'
```

## 2. Create a resource folder

The following command creates a top-level resource folder named **Support resources**. The response contains the ID of the newly created folder; save this for a later step.

```shell
curl -X POST https://{space-domain}/api/v2/folders -H 'Authorization: Bearer $BEARER_TOKEN' -H 'Content-Type: application/json' --data '{"name": "Support resources", "parent_folder_id": null, "folder_type": "resource"}'
```

## 3. Update and create permission groups

By default, the **All users** group has **Use** access to apps and resources. To ensure new Retool users have restricted access unless they're explicitly added to a permission group, set the universal access level for **All users** to **None**.

If you don't know the ID for the **All users** group, use the `GET /groups` endpoint to retrieve it.

```shell
curl -X PATCH https://{space-domain}/api/v2/groups/1 -H 'Authorization: Bearer $BEARER_TOKEN' -H 'Content-Type: application/json' --data '{"operations": [{"op": "replace", "path": "universal_app_access", "value": "none"}]}'
```

Next, create a new permission group. Save its ID for later steps.

```shell
curl -X POST https://{space-domain}/api/v2/groups -H 'Authorization: Bearer $BEARER_TOKEN' -H 'Content-Type: application/json' --data '{"name": "Support team", "universal_app_access": "none", "universal_resource_access": "user", "members": []}'
```

## 4. Set folder permissions

Grant the newly created permission group access to the new app and resource folders with the following command. Replace `GROUP_ID` with the ID of your new permission group, and `APP_FOLDER_ID` and `RESOURCE_FOLDER_ID` with the IDs of your new app and resource folders.

```shell
curl -X POST https://{space-domain}/api/v2/permissions/grant -H 'Authorization: Bearer $BEARER_TOKEN' -H 'Content-Type: application/json' --data '{"subject": {"id": GROUP_ID, "type": "group"}, "object": {"id": APP_FOLDER_ID, "type": "folder"}, "access_level": "edit"}'
```

```shell
curl -X POST https://{space-domain}/api/v2/permissions/grant -H 'Authorization: Bearer $BEARER_TOKEN' -H 'Content-Type: application/json' --data '{"subject": {"id": GROUP_ID, "type": "group"}, "object": {"id": RESOURCE_FOLDER_ID, "type": "folder"}, "access_level": "edit"}'
```

## 5. Provision and map users

Create users in Retool.

```shell
curl -X POST https://{space-domain}/api/v2/users -H 'Authorization: Bearer $BEARER_TOKEN' -H 'Content-Type: application/json' --data '{"first_name": "Test", "last_name": "User", "active": true, "email": "testuser@retool.com"}'
```

Use the newly created user IDs to add users to the new permission group, and optionally set any certain users as admins.

```shell
curl -X POST https://{space-domain}/api/v2/groups/{GROUP_ID}/members -H 'Authorization: Bearer $BEARER_TOKEN' -H 'Content-Type: application/json' --data '{[{"id": USER_ID, "is_group_admin": false}]}'
```

## 6. Wrap up

You can confirm the onboarding flow correctly created app folders, groups, and users from the **Settings > Permissions** page. You should see the newly created permission group, and within it, a new member. The **Apps** and **Resources** tabs should reflect the new apps and folders.

To further streamline onboarding, you can add the Retool API as a resource and create an app or workflow to trigger these steps based on user input.

---

## Automate Spaces configuration using the Retool API

If you need to configure many [Spaces](../../tutorials/spaces.mdx), you may want to programmatically configure them with the Retool API, rather than manually create and configure every Space. You can use the commands in this guide within Retool apps, workflows, or other scripts to streamline Spaces configuration.

## Requirements

The [Retool API](../../../api/index.mdx) is available to cloud organizations and self-hosted organizations running v3.18 or later. API users must generate [access tokens](authentication.mdx) to authenticate. This guide assumes you have an access token with **Read and Write** scopes for users, permissions, and Spaces.

## 1. Get existing spaces

From the Admin Space, use the following command to retrieve all existing Spaces.

```shell
curl -X GET https://{ADMIN_SPACE_DOMAIN}/api/v2/spaces -H 'Authorization: Bearer $BEARER_TOKEN'
```

## 2. Edit theme

From the child Space, update the theme.

```shell
curl -X PUT https://{CHILD_SPACE_DOMAIN}/api/v2/app_themes -H 'Authorization: Bearer $BEARER_TOKEN' -H 'Content-Type: application/json' --data '{"name": "Default theme", "theme": {"info": "hsl(208, 70%, 55%)", "canvas": "#FFFFFF", "danger": "#CA483F", "primary": "#128747", "success": "#128747", "warning": "#D17823", "tertiary": "#034822", "textDark": "#262626", "highlight": "#f6e5c4","secondary": "#d7eae0", "textLight": "#FFFFFF", "borderRadius": "4px", "surfacePrimary": "#FFFFFF", "surfaceSecondary": "#F9F9F9"}}'
```

## 3. Edit SSO configuration

From the child Space, update the SSO configuration. Refer to the [SSO](../../../sso/index.mdx) documentation for more detail on SSO fields.

```shell
curl -X POST https://{CHILD_SPACE_DOMAIN}/api/v2/sso/config -H 'Authorization: Bearer $BEARER_TOKEN' -H 'Content-Type: application/json' --data
'{"data": {"config_type": "google", "google_client_id": "GOOGLE_CLIENT_ID", "google_client_secret": "GOOGLE_SECRET", "disable_email_password_login": false}}'
```

## 4. Create a Source Control configuration

:::warning

To use Spaces with Source Control, ensure you [migrate your apps to Toolscript](/changelog/yaml-serialization-deprecation).

:::

From the child Space, create a [Source Control](../../../source-control/index.mdx) configuration.

```shell
curl -X POST https://{CHILD_SPACE_DOMAIN}/api/v2/source_control/config -H 'Authorization: Bearer $BEARER_TOKEN' -H 'Content-Type: application/json' --data {"config": {"config": {"type": "App", "app_id": "app_id", "installation_id": "installation_id", "private_key": PRIVATE_KEY, "url": "string", "enterprise_api_url": "string"}, "provider": "GitHub", "org": "github_organization", "repo": "github_repo", "default_branch": "main"}}
```

## 5. Create additional Spaces

You can generate a new Space with settings automatically copied over from an existing Space. Set `copy_sso_settings` and `copy_branding_and_themes_settings`. When you create spaces programmatically, you also must set `create_admin_user` to `true`. This creates a default admin user with the email of the API key creator.

```shell
curl -X POST https://{ADMIN_SPACE_DOMAIN}/api/v2/spaces -H 'Authorization: Bearer $BEARER_TOKEN' -H 'Content-Type: application/json' --data '{"name": "Finance", "domain": "finance.sample-org.dev", "options": {"copy_sso_settings": true, "copy_branding_and_themes_settings": true, "create_admin_user": true}}'
```

---

## Retool API how-to guides



---

## User management how-to guides



---

## Enable two-factor authentication

Two-factor authentication (2FA) provides an additional level of security. Admins can enable two-factor authentication so that users must either enter a one-time passcode (OTP) generated by an authenticator app or use a security key (FIDO2) each time they log in.

:::note Two-factor authentication for individual users

Users in organizations on the Enterprise plan can enable two-factor authentication for their account even if it's not required for the organization **Settings** > **Account**.

:::

### Enforce two-factor authentication

Admins can manage two-factor authentication enforcement by navigating to **Settings** > **Advanced**. Set the **Require Two Factor Authentication** option to either the **OTP** or **FIDO2** method. The next time a user logs in, they will have to configure two-factor authentication before they can continue.

To disable organization-wide two-factor authentication, change this option to **None**.

## Set up OTP authentication

OTP requires a compatible authenticator app, such as 1Password, Authy, and Google Authenticator. To set up:

1. Scan the QR code with the authenticator app.
2. Enter the generated one-time passcode to confirm and complete set up.

Whenever a user attempts to sign in, they must also enter a generated one-time passcode.

## Set up FIDO2 authentication

:::caution Use OTP when using Retool Mobile

FIDO 2FA is not supported in Retool mobile apps. Use OTP 2FA instead.

:::

FIDO2 requires a FIDO2-complaint security key. This can be either a hardware key (e.g., Yubikey) or a supported security key method (e.g., [passkey](https://blog.1password.com/what-are-passkeys/)). Support for available options depend on the user's device and browser.

FIDO2 setup is handled by the user's browser. Follow the instructions to set up a hardware key or passkey. 

## Reset two-factor authentication for individual users

:::warning Keep your two-factor authentication details secure

If you're the only admin of your organization and lose access to your two-factor authentication method, contact our [contact our support team](mailto:support@retool.com).

:::

Retool administrators can reset 2FA for individual users in the Users settings. Navigate to **Settings** > **Users**, then click the `...` menu for the user. Once reset, the user must setup 2FA again the next time they log in.

Users of Retool organizations on the Enterprise plan can also reset their own 2FA from **Settings** > **Account**.

---

## Configure user attributes

Often, information about Retool users exists in systems outside of Retool. With user attributes, you can bring this information into Retool and store it on the user–across all of your Retool apps.

You can create and add attributes to users to enable custom experiences in Retool. Admins can create and apply attributes to any Retool user. When building Retool apps, you can reference attributes through the `current_user` object to control functionality. Attributes are secure by default: bad actors cannot spoof data passed into queries that reference attributes.

## Create user attributes

To create a user attribute, go to **Settings** > **User attributes**. Add a name as your key, a label for readability, and data type.

User attributes support the following data types:

- String: Can contain letters, numbers, symbols, and spaces (e.g., username or account tier).
- Number: Supports floating point values.
- JSON: Stored as an object.

Optionally, you can add a default value to be applied across all users. When a value is not assigned to the user, the default value is set.

## Assign attribute values to users

:::info Retool API

You can also assign and delete user attributes using User Attributes endpoints in the [Retool API](../../../api/add-or-update-user-attributes-on-a-user-invite.api.mdx).

:::

Admins can assign attribute values directly to users from **Settings > Users**. Under **User Attributes**, update and reset user attribute values. Resetting an attribute value clears it, or reverts it to its default value if one is set.

You cannot delete an attribute key from a user without first deleting the attribute at the organizational level.

:::note Using custom authentication with Retool API

If you [embed external apps](../../../apps/guides/app-management/embed-apps.mdx) or use the [SCIM API](../../../scim/index.mdx), and passing values into the `metadata` property, those values will also be available on the `current_user.metadata` object. If an attribute with the same name already exists, respecting the attribute type, Retool will set its value with the value in the API request.

:::

### Use in Retool apps

When editing a Retool app, you can reference user attributes through `current_user.metadata.`. Add logic referencing these attributes to hide and show components based on attributes set on the user, filter data, and more.

Setting default values is also especially useful when building Retool apps that might reference nested values. This way, you can ensure the schema across users is consistent and doesn't vary between applications.

### Row-level security

When implementing [row-level security](../../../queries/concepts/row-level-security.mdx), many customers maintain mapping tables from the Retool user's email or permission group to foreign keys in their database. To save a `JOIN` operation and maintenance, you can add these foreign keys directly to the user as attributes.

---

## Administration how-to guides

import Howto from '/docs/_partials/_doctypes/_howto.mdx';

:::tip Get started

Read the [quickstart](./quickstart) to learn about the fundamental concepts for Retool administration.

:::

---

## Administration documentation

Manage your Retool organization, manage users, create isolated spaces for teams, and more.

---

## Administration quickstart

This guide serves as an introduction to Retool administration. It covers many of the concepts and terminology you would come across when managing or working within a Retool organization. After reading this page, you should have a good understanding of the fundamentals for organizations and users.

## Introduction

A Retool _organization_ is a distinct collection of users and data. Organizations operate separately from one another, have their own configuration settings, and are where users share access to work.

Each cloud-hosted organization has its own `.retool.com` subdomain, such as `https://example.retool.com`. Self-hosted organizations use the URL for their deployment and may have multiple instances.

## Spaces

Spaces are an organizational feature that allow you to create multiple isolated Retool organizations. These spaces exist within the same parent organization and provide a multitenant experience. Each space has its own:

- Subdomain of your Retool organization (e.g., `space1.example.retool.com`).
- SSO configuration.
- Source Control configuration.
- User accounts and permission groups.
- Retool Database.
- Data (folders, apps, workflows, resources, etc.)

Spaces are useful when:

- Your teams want to have separate source control repositories and sets of apps available to them.
- You have isolated use cases which don't overlap with the rest of your Retool usage: e.g., you want to create a suite of “performance review” apps or an external portal, each with its own set of users, apps, and resources.
- You want to delegate administration of Retool to a distributed set of admins, based on the apps they’ll be overseeing.

## Users

:::tip User billing

Refer to the [billing and usage](/support/billing-usage) documentation to learn more about the different user types that relate to billing.

:::

A _Retool user_ is a Retool account that belongs or has access to an organization. Users represent the people with access to the organization and its data. Retool uses email addresses as the identifier for users.

When a user signs up, Retool associates them with an existing organization if the user meets one of the following conditions:

- They use an invitation from an existing organization.
- Their email address domain matches one configured by an existing organization to automatically add users from that domain.
- They use an SSO provider configured for an existing organization.

Retool uses the email address as the identifier for a user and associates it with an organization at signup. This can be an existing organization if the user meets certain conditions or a new organization for which the user is the primary admin.

If the user doesn't meet these conditions during signup, Retool prompts them to create a new organization for which they become the primary admin.

import Email from "./_partials/_email.mdx"

### Drafts

The **Drafts** tab of the Apps landing page is a personal folder for [builders](/support/billing-usage#user-types) to develop and test apps. Only you and organization admins have access to view or edit apps that you create in this section. This feature is useful for organizations where creating applications and folders is restricted—admins don't have to give users explicit permission to create apps in their **Drafts**.

You cannot share an app that is currently in the **Drafts** folder with other users. Once the app is ready to be shared with other users, move the app to a different folder in the organization so it can then be accessed by others.

Admins can see draft apps for all users in the organization using the **Users' drafts** filter.

**Drafts** are enabled by default. Admins can toggle off this feature by navigating to **Settings** > **Beta** and turning off **Drafts folders**.

### External users

Organizations can [embed web apps](../apps/concepts/share-externally/embed.mdx) into their own web-based applications for use by external users, such as customers, vendors, or partners. An external user is not considered part of a Retool organization and can only access apps for which they have access.

External users priced at the same rate as internal users on the Team and Business [plans](https://retool.com/pricing). However, usage for external use cases varies and the default pricing might not work for everyone. If you're pre-product or have hundreds of thousands of users, [talk to our team](https://retool.com/demo/?meeting_page_source=docs) to learn more.

Refer to [External users](./concepts/external-users.mdx) for more information about external users.

### Authentication

Retool manages authentication of users for your organization. The available methods and process depend on your subscription plan and whether you use an SSO identity provider (idP). Retool organizations on every plan can use Sign in with Google. Organizations on the Enterprise plan can configure additional SAML and OIDC providers.

Regardless of authentication method, new users must be added to relevant [permission groups](../permissions/tutorial.mdx) to grant them required access. You can either configure the SSO authentication flow to handle this automatically or you can manually [configure user permissions](../permissions/guides/configure-permission-groups.mdx).

Retool supports Sign in with Google. You can sign in using your existing Google account. Retool creates a new organization if you're not an existing user.

If your organization uses [Google Workspace](https://workspace.google.com/) and all users share the same domain, users can select **Sign in with Google** and log in automatically to the same Retool organization. If you attempt to sign in with Google and there is no existing organization, Retool creates one and assigns you as an administrator.

Retool accounts use an email address and password which operates separately from Sign in with Google. You can specify a set of domains from which to allow users with a matching email address to join. Navigate to **Settings > Advanced**, then add one or more domains to the **Auto-join domain** section. You then specify whether users with a matching email address can request to join or join automatically for that domain.

When auto-join is disabled, anyone who signs up to Retool with a username and password creates a new organization, regardless of whether the email address shares a domain with an existing Retool organization. To join an organization using email and password instead of creating a new one, they will need to receive an invitation.

[SSO](../sso/index.mdx) is a user authentication tool that enables users to securely access multiple applications and services using one set of credentials. Rather than require users to create additional usernames and passwords for Retool, you can centralize logins to a single identity provider (IdP). SSO is primarily used for authentication, though Retool also supports syncing groups for authorization.

## Retool API

The [Retool API](../api/index.mdx) enables Retool admins to programmatically manage different aspects of their organization, such as:

- Access control
  - Users
  - Groups
  - Permissions
  - SSO
- Apps and themes
- Resources and resource environments
- Folders for apps, resources, and workflows
- Spaces
- Source Control

Retool also implements a subset of the [SCIM 2.0 API](../scim/index.mdx). This adheres to the [SCIM 2.0 Protocol](https://developer.okta.com/docs/reference/scim/scim-20/) that is used by identity providers (e.g., Okta) to automatically provision users and map groups.

While there is overlap between functionality in the Retool API and SCIM 2.0 API, use the Retool API for automating operations when possible.

## Retool Events

Retool Events allow organizations to build workflows that trigger automatically in response to actions taken in Retool. These workflows can then perform custom actions, such as sending custom onboarding emails to new users or notifying admins about certain actions that occur.

You can even [configure branding options](../apps/guides/app-management/external-apps/index.mdx#configure-branding) to replace Retool's built-in email notifications with workflows that send custom transactional emails with a reply-to address at your domain. When doing so, you should set up appropriate alerts as error handlers in your workflows.

Read the [Retool Events workflow](../workflows/guides/retool-events.mdx) tutorial to learn more.

---

## Organizations and users glossary

import SharedGlossary from '../../_partials/_glossary.mdx';

---

## Audit trail logged events

By default, Retool captures the following events in the audit log. Refer to the [View user audit logs](../guides/monitoring/audit-logs.mdx) page for more information.

| Identifier in logs                     | Action                                                           |
|----------------------------------------|------------------------------------------------------------------|
| `ACCESS_TOKEN_CREATED`                 | An access token was created.                                     |
| `ACCESS_TOKEN_REVOKED`                 | An access token was revoked.                                     |
| `ADD_PAGE_TO_GROUP`                    | A page was added to a group.                                     |
| `ADD_USERS_TO_GROUP`                   | A user added other users to a group.                             |
| `ANALYTICS_CONFIG_CREATED`             | An analytics configuration was created.                          |
| `ANALYTICS_CONFIG_DELETED`             | An analytics configuration was deleted.                          |
| `ANALYTICS_CONFIG_UPDATED`             | An analytics configuration was updated.                          |
| `ARCHIVE_ORGANIZATION`                 | An organization was archived.                                    |
| `ARCHIVE_USER`                         | A user account was archived.                                     |
| `CANCEL_USER_TASK`                     | A user task was cancelled.                                       |
| `CONFIG_VAR_CREATE`                    | A configuration variable was created.                            |
| `CONFIG_VAR_DELETE`                    | A configuration variable was deleted.                            |
| `CONFIG_VAR_UPDATE`                    | A configuration variable was updated.                            |
| `CONFIRM_PASSWORD_RESET_LINK`          | A user confirms a password reset request.                        |
| `CREATE_EVENT_WORKFLOW`                | An event-based workflow was created.                             |
| `CREATE_GROUP`                         | A user created a group.                                          |
| `CREATE_RESOURCE`                      | A user created a resource.                                       |
| `CREATE_ROLE`                          | A new role was created.                                          |
| `CREATE_USER`                          | A new user account was created.                                  |
| `CREATE_USER_TASK`                     | A user task was created.                                         |
| `CREATE_WORKFLOW`                      | A user created a workflow.                                       |
| `DATASOURCE_CREATE`                    | A new data source was created.                                   |
| `DELETE_EVENT_WORKFLOW`                | An event-based workflow was deleted.                             |
| `DELETE_GROUP`                         | A user deleted a group.                                          |
| `DELETE_RESOURCE`                      | A user deleted a resource.                                       |
| `DELETE_ROLE`                          | A role was deleted.                                              |
| `DELETE_USER`                          | A user account was deleted.                                      |
| `DELETE_WORKFLOW`                      | A user deleted a workflow.                                       |
| `DIRECTLY_SHARE_PAGE_WITH_USER`        | A page was directly shared with a user.                          |
| `DISABLE_RETOOL_DEFAULT_EMAIL`         | The default Retool email notifications were disabled.            |
| `DISABLE_TRIGGER`                      | A user disabled a workflow trigger.                              |
| `DISABLE_TWO_FACTOR_AUTH`              | A user disabled two-factor authentication.                       |
| `DISABLE_USER`                         | A user disabled another user.                                    |
| `DISABLE_WORKFLOW`                     | A workflow was disabled.                                         |
| `DOWNLOAD_AUDIT_LOGS`                  | Audit logs were downloaded.                                      |
| `ENABLE_TRIGGER`                       | A user enabled a workflow trigger.                               |
| `ENABLE_USER`                          | A user enabled another user.                                     |
| `ENABLE_WORKFLOW`                      | A workflow was enabled.                                          |
| `INVITE_USER`                          | A user invited another user.                                     |
| `LOGIN`                                | A user logged in.                                                |
| `LOGIN_FAILED`                         | A user login attempt failed.                                     |
| `LOGOUT`                               | A user logged out.                                               |
| `MODIFY_PERMISSIONS`                   | Permissions were modified.                                       |
| `PAGE_EXPORT`                          | A user exported a page.                                          |
| `PAGE_VIEW`                            | Page views.                                                      |
| `PLAYGROUND_QUERY_RUN`                 | A user ran a query in the Query Library.                         |
| `QUERY_PREVIEW`                        | Query tests (preview runs).                                      |
| `QUERY_RUN`                            | Query runs (executed in production or live context).             |
| `RE_INVITE_USER`                       | A user re-sent an invite.                                        |
| `REASSIGN_USER_TASK`                   | A user task was reassigned.                                      |
| `REDEEM_INVITE`                        | A user redeemed an invite.                                       |
| `RELEASE_WORKFLOW`                     | A user released a workflow.                                      |
| `REMOVE_PAGE_FROM_GROUP`               | A page was removed from a group.                                 |
| `REMOVE_TWO_FACTOR_AUTHENTICATOR`      | Two-factor authentication device was removed.                    |
| `REMOVE_USER_FROM_GROUP`               | A user was removed from a group.                                 |
| `REMOVE_USERS_FROM_GROUP`              | A user removed other users from a group.                         |
| `REQUEST_PASSWORD_RESET_LINK`          | A user requested a password reset link.                          |
| `REQUEST_PASSWORDLESS_LOGIN`           | A user requested passwordless login.                             |
| `REQUEST_PASSWORDLESS_TOKEN`           | A passwordless login token was requested.                        |
| `RESET_GOOGLE_ID`                      | A user's Google ID was reset.                                    |
| `RESET_RETOOLDB_PASSWORD`              | The RetoolDB password was reset.                                 |
| `RETOOL_AI_FEATURE_CHANGED`            | A Retool AI feature setting was changed.                         |
| `RETOOL_STORAGE_FILE_ACCESSED`         | A file in Retool Storage was accessed.                           |
| `RETOOL_STORAGE_FILE_DELETED`          | A file in Retool Storage was deleted.                            |
| `RETOOL_STORAGE_FILE_METADATA_RETRIEVED`| Metadata for a Retool Storage file was retrieved.                |
| `RETOOL_STORAGE_FILE_MOVED`            | A file in Retool Storage was moved.                              |
| `RETOOL_STORAGE_FILE_UPDATED`          | A file in Retool Storage was updated.                            |
| `RETOOL_STORAGE_FILE_UPLOADED`         | A file was uploaded to Retool Storage.                           |
| `RETOOL_STORAGE_FILES_LISTED`          | Files in Retool Storage were listed.                             |
| `RETOOL_STORAGE_FOLDER_CREATED`        | A folder was created in Retool Storage.                          |
| `RETOOL_STORAGE_FOLDER_DELETED`        | A folder was deleted in Retool Storage.                          |
| `RETOOL_STORAGE_FOLDER_RENAMED`        | A folder in Retool Storage was renamed.                          |
| `RETOOL_STORAGE_FOLDERS_LISTED`        | Folders in Retool Storage were listed.                           |
| `REVEAL_RETOOLDB_CONNECTION_STRING`    | The RetoolDB connection string was revealed.                     |
| `RUN_WORKFLOW`                         | A user ran a workflow manually.                                  |
| `RUN_WORKFLOW_BLOCK`                   | A user ran a workflow block manually.                            |
| `SEND_MAGIC_LOGIN`                     | A magic login link was sent.                                     |
| `SIGN_UP`                              | A user signed up.                                                |
| `SOURCE_CONTROL_CONFIG_UPDATE`         | Source control configuration was updated.                        |
| `SOURCE_CONTROL_DEPLOYMENT_FINISHED`   | A source control deployment finished.                            |
| `SOURCE_CONTROL_SETTINGS_UPDATE`       | Source control settings were updated.                            |
| `SUBMIT_USER_TASK`                     | A user task was submitted.                                       |
| `SUGGEST_USER`                         | A user was suggested (e.g., for assignment or sharing).          |
| `UPDATE_BILLING_PLAN`                  | The billing plan was updated.                                    |
| `UPDATE_GROUP`                         | A group was updated.                                             |
| `UPDATE_ORGANIZATION`                  | A user updated an organization.                                  |
| `UPDATE_RESOURCE`                      | A user updated a resource.                                       |
| `UPDATE_ROLE`                          | A role was updated.                                              |
| `USER_CHANGED_EMAIL_AND_VERIFY`        | A user changed their email and verified it.                      |
| `USER_EMAIL_CHANGE`                    | A user changed their email address.                              |
| `USER_EMAIL_CHANGE_NOTIFICATION_SENT`  | Notification sent about a user's email change.                   |
| `USER_EMAIL_VERIFICATION_SENT`         | Email verification was sent to a user.                           |
| `USER_EMAIL_VERIFY`                    | A user verified their email address.                             |
| `USER_NAME_CHANGE`                     | A user changed their name.                                       |
| `VERIFY_2FA_FAILURE`                   | Two-factor authentication verification failed.                   |
| `VERIFY_2FA_SUCCESS`                   | Two-factor authentication verification succeeded.                |
| `VIEW_WORKFLOW`                        | A user viewed a workflow.                                        |

---

## Administration reference

import Reference from '/docs/_partials/_doctypes/_reference.mdx';

:::tip Get started with your organization and users

If you are unfamiliar with managing your organization and want to get started, read the [quickstart](./quickstart) to learn about the fundamental concepts.

:::

---

## Manage organization users

Retool provides several options for admins to add users to their organization:

- Invite users to sign up with an email address and password.
- Allow users to request access to your organization.
- Specify a list of domains to automatically add users with matching email addresses.
- Configure SSO and allow users to sign in using your SSO provider.
- Receive notifications about suggested users.

You can also disable users to prevent them from accessing the organization at any time.

## Invite users

:::caution

Users needing to sign in with an email and password must first be invited to a Retool Cloud organization. If they attempt to sign up first, Retool creates a new organization and adds them to it.

:::

You can invite users to join your Retool organization. New users can create an account with their email address and password, or sign in using SSO.

To invite a user:

1. Click the User menu on the upper-right, then select **Settings**.
2. Select the **Users** settings in the **User management** section of the sidebar.
3. Click **Invite**, then enter the email addresses of users to invite.
4. Retool sends an invite URL to the users you specified. This URL expires after one week.

Admins can also invite users directly from an app by clicking **Share**.

For organizations on the Enterprise plan, users can sign up using the URL of your deployment's sign up page. 

Retool [strongly recommends disabling signups and enforcing SSO usage](../quickstart.mdx#authentication#sso-providers-for-self-hosted-retool).

export function InviteUser() {
  return (
    
      
    
  )
}

## Allow users to request access

To enable users to request access to join your Retool organization, go to **Settings > Advanced Settings** and toggle **Allow anyone to request to join**.

Enabling this settings adds a link to your organization login page (`.retool.com/auth/login>`) prompting users to enter a valid email address. 

Visit **Settings > Users** to approve an access request. After approving, the user receives an email to join your Retool organization.

## Configure auto-join domains

Retool Cloud organizations can specify a set of domains from which to allow users with a matching email address to join. Navigate to **Settings > Advanced Settings**, then add one or more domains to the **Auto-join domains** section. You then specify whether users with a matching email address can either request to join or join automatically for that domain.

:::note

Auto-joining domains is not supported for self-hosted organizations.

:::

## Add SSO users

Retool Cloud supports Sign in with Google on all pricing plans. Organizations on the Enterprise plan can configure other supported SSO providers, such as [Okta]( ../../sso/tutorials/okta/oidc.mdx).

If you have a Retool Cloud organization and use [Google Workspace](https://workspace.google.com/), all users who share the same domain can select **Sign in with Google** and log in. Users are automatically added to your Retool Cloud organization.

Organizations on the Enterprise plan can configure additional SSO providers. Users can then sign in automatically, but [additional steps are required](../quickstart.mdx#authentication#sso-providers-for-self-hosted-retool) before they have access.

:::tip Generate auto-join links for mobile-only users

You can generate an **auto-join link** from a mobile app's [share options](../../mobile/guides/deploy/deployment.mdx#share-apps-and-invite-users) that allows users to sign up directly from the Retool Mobile app using SSO. Users who sign up using this method are added as mobile-only users. You must [configure auto-join domains](#configure-auto-join-domains) to enable this option.

:::

## Suggest users

Retool users who aren't administrators can notify admins about users who might need access. To suggest a user, navigate to **Settings > Users** and click **Suggest**. Users can provide email addresses for potential users and click **Suggest new members**.

Retool organization admins receive a notification and can decide whether to add or invite users.

## Disable users

Retool organization admins can disable access of any user within their Retool organization. Disabling users prevents them from logging into their Retool account, as well as accessing or editing any apps, queries, or resources in your shared Retool organization.

You can disable users from your organization's [Users](https://login.retool.com/auth/login?source=docs&redirectOnLogin=settings/users) settings. Select a user, then click **Disable user**.

You can enable a disabled user by clicking *...* next to their name, then **Enable user**. If you don't see the disabled user in the users list, ensure **Hide disabled users** is not selected in the user filters.

---

## Spaces tutorial

Retool Spaces is an organizational feature that allows you to split your Retool organization into multiple isolated ones, creating a multitenant experience. After enabling Retool Spaces, you retain your original organization as an **Admin Space**, and you can create any number of alternative spaces.

Each space has its own:

- Subdomain
- SSO configuration
- Source Control configuration
- User accounts and permission groups
- Retool Database
- Folders, apps, workflows, modules, queries, resources, etc.

Spaces are useful when:

- Your teams want to have separate source control repositories and sets of apps available to them.
- You have isolated use cases which don't overlap with the rest of your Retool usage: for example, you want to create a suite of “performance review” apps or an external portal, each with its own set of users, apps, and resources.
- You want to delegate administration of Retool to a distributed set of admins, based on the apps they’ll be overseeing.

See the guide to [governance on Retool](../concepts/governance.mdx) to learn when to use Retool Spaces, multiple instances, and permission groups.

## Initial setup and Admin Space

Navigate to **Settings > Spaces** to enable Retool Spaces. This sets up Retool Spaces and provisions SSL certificates, which typically takes around five minutes. Once it is finished, you can begin to create spaces.

By default, new self-hosted Retool instances are configured with one space. This space looks and behaves exactly the same as a new instance without spaces—you spin up the instance, and then create the first account, which becomes its admin, in this space. The first space is the **Admin Space**. If you're self-hosting Retool, when you upgrade an existing instance to a version with spaces, the existing organization becomes the **Admin Space**.

If you anticipate needing multiple spaces, consider keeping the **Admin Space** free of apps, and use it only for superadmin responsibilities.

## Create spaces

Admin users of the **Admin Space** can create and manage spaces from **Settings > Spaces**, or use the [Retool API](../../api/index.mdx). Each space must have a name, description, and associated subdomain. You can choose to automatically copy over SSO, branding, and theme settings from the current organization.

### Configure domains

The domain of your **Admin Space** does not change. If the domain on which you enable Retool Spaces is `example.retool.com`, every other space is automatically located as a subdomain (for example, `testing.example.retool.com`).

You can [change the subdomain](../guides/cloud/change-subdomain.mdx) or create a [custom domain](../guides/cloud/custom-domains.mdx) for any space after it's created.

If you're self-hosting Retool, the domain of each space must point to the current instance and have a correct SSL certificate. Users can navigate directly to the space using this domain.

:::note

To avoid configuring a domain for each new space, you can set up a wildcard subdomain in your DNS settings—for example, `*.retool.mycorp.com`—and secure it with a matching wildcard SSL certificate. You can then create new spaces with arbitrary subdomains that match the wildcard without having to update your DNS again. You can set any level of subdomain—for example, `*.mycorp.com`, `*.retool.mycorp.com`, and `*.retool.prod.mycorp.com` are all possible subdomains.

Retool expects the domain name to be passed via `Host` header to the backend. If your self-hosted instance has proxy or load balancer in front of Retool backend, make sure it's configured to set `Host` header to the host used in the original request.

Not all Identity Providers support wildcard domains. When setting up SSO for your spaces, make sure your Identity Provider is compatible with wildcards.

:::

### Log in to new spaces

The admin of the new space can log in using the following methods:

- If SSO was copied over for the new space, Retool creates an admin account for this superadmin on the new space. They can use their exisiting SSO account to log in directly to the new space.
- If SSO hasn’t been configured for the space, the admin needs to log in by resetting the password associated with their email address.

You can add users from any permission group to your space, including admin users. However, only admin users of the  **Admin Space** can create new spaces.

## Configure spaces

Admins can customize SSO, invite users, configure source control, and update settings on spaces the same way they update settings on existing organizations.

:::tip

You can also use the [Retool API](../../api/) to programmatically configure spaces. See the [guide](../guides/retool-api/automate-spaces.mdx) for more information.

:::

### Spaces and SSO

Each space has its own SSO configuration, but you can copy existing SSO settings to a new space when you create it. Since each space has a different domain name, you must confirm that a correct callback URL is configured in your IdP. Most IdPs allow you to add multiple callback URLs; you need to add one for each space. Some IdPs, like Auth0, support wildcards in callback URLs.

Okta's Retool integration accepts a single domain name in its configuration, so you need to configure a separate Okta app for each space, or use the generic OIDC or SAML app configuration to provide multiple callback URLs.

Spaces can also use different SSO settings depending on their use cases. For example, a general-purpose space with apps for everyone at your company might use JIT provisioning. A space for use with only a finance team might need explicit user provisioning.

#### SSO settings and environment variables

When you use environment variables to configure SSO settings, those settings apply to all spaces, unless you override them per space from **Settings > SSO**.

This applies to all SSO settings except those used for SCIM provisioning. The `SCIM_AUTH_TOKEN` environment variable only applies to the **Admin Space** and is not supported on other spaces. To use SCIM provisioning on a non-admin space, navigate to **Settings > API**, and create an access token with the `scim` scope.

### Spaces and Source Control

:::warning

To use Retool Spaces with Source Control, ensure you [migrate your apps to Toolscript](/changelog/yaml-serialization-deprecation).

:::

Each space has its own separate [Source Control](../../source-control/index.mdx) configuration, so it can connect to a different Git repository or an entirely different SCM provider. For each new space, you need to set up Source Control to point to the repository that you want to link to the space.

Multiple spaces can also connect to a single Git repository. For example, you might want to use spaces to represent different dev, staging, and prod instances. These spaces function the same as multiple instances connected to the same Git repository—you can choose which branch to point to by default, and sync changes when commits are merged into this branch.

### Spaces and Retool Database

Each space has its own [Retool Database](../../data-sources/quickstarts/retool-database.mdx). If you already configured an [external PostgreSQL cluster](../../data-sources/quickstarts/retool-database.mdx) to use on your self-hosted instance, you can connect the new Space's Retool Database to the same cluster. Each space automatically creates a new database in the cluster.

### Switch between spaces

Users can have accounts in multiple spaces and switch between them. From the navigation bar, users can navigate between the spaces to which they belong. Users must log in to each space separately.

### Copy across spaces

For organizations on the Enterprise plan on Retool Cloud and self-hosted Retool versions 3.41 and later, admins can copy apps, resources, Query Library queries, and workflows across spaces. The following applies to all copied items:

- Copies are unprotected in the destination space.
- Copied resources are created in the destination space's default resource environment.
- All dependencies except environment variables are copied to the destination space. You must configure environment variables in the destination space.
- Releases, permissions, and unit tests are not copied to the destination space.

---

## Administration tutorials

import Tutorial from '/docs/_partials/_doctypes/_tutorial.mdx';

---

## _access Rules

Permission groups use [access rules](../quickstart.mdx#access-rules) that determine the apps, resources configuration, and workflows that members can access. Access rules can also apply to folders in which these are organized.

Select the **Apps**, **Resources**, **Workflows**, or **Agents** tab to configure their respective access rules. The **Select type** option enables you to define specific access by configuring access individually, or apply **Use all**, **Edit all**, or **Own all**.

:::note

Folder permissions are inherited. Giving a user **Edit** access to a folder will also give that user **Edit** access to all of the items within that folder.

:::

---

## _add To Group

Click **Add new members** to add users to the group. You can search the list of users and select multiple users to add. Click **Select all** to select all users currently visible, then click **Add to group**.

---

## _agents Perm Levels

When interacting with an agent, a user is a member of a permission group for both the agent and the resource, and the following rules are observed.

  
     
    **AGENT PERMISSION LEVEL**
  
  
    **RESOURCE PERMISSION LEVEL**
     
    **NONE**
    **USE**
    **EDIT**
    **OWN**
  
  
     **NONE**
     Cannot interact with an agent, cannot call a tool on any resource. 
     Can interact with an agent. If the agent calls a tool that the user does not have permission to use, an error message is displayed.
     Can modify an agent’s configuration, but can only reference a resource in a tool if the user also has permissions to use the resource.
     Can modify an agent’s configuration, delete, and rename the agent, but can only reference a resource in a tool if the user also has permissions to use the resource.
  
  
     **USE**
     Cannot interact with an agent, cannot call a tool on any resource. 
     Can interact with an agent. Can call tools. 
     Can modify an agent. Can add and call tools.
     Can modify, delete, or rename an agent. Can add and call tools.
  
  
     **EDIT**
     Cannot interact with an agent, cannot call a tool on any resource. 
     Can interact with an agent. Can call tools. 
     Can modify an agent. Can add and call tools.
     Can modify, delete, or rename an agent. Can add and call tools.
  
  
     **OWN**
     Cannot interact with an agent, cannot call a tool on any resource. 
     Can interact with an agent. Can call tools. 
     Can modify an agent. Can add and call tools.
     Can modify, delete, or rename an agent. Can add and call tools.
  

The visibility of certain tabs within Retool Agents is also limited based on permissions:

 | Tabs             | Use       | Edit           | Own            |
 |------------------| ----------| ---------------| ---------------|
 | Chats            | Access    | Access         | Access         |
 | Configuration    | No access | Access         | Access         |
 | Logs             | No access | Access         | Access         |
 | Evals            | No access | Access         | Access         |

---

## _default Groups

The default groups and permissions differ depending on the plan your organization uses.  All pricing plans have **Admin** and **All Users** groups. Business and Enterprise plan users have more granular control over groups, and can create their own [custom groups](#custom-permission-groups). 

The following built-in permission groups cannot be modified or removed, and the access levels cannot be changed.

| Group         | Apps | Workflows | Agents    | Resources |
| ------------- | ---- | --------- | --------- | --------- |
| **All Users** | Edit | Edit      | Edit      | Own       | 
| **Admin**     | Own  | Own       | Own       | Own       |

The following built-in permission groups cannot be modified or removed. These are preconfigured with default permission levels, which can be updated by an admin.

| Group         | Apps | Workflows | Agents    | Resources |
| ------------- | ---- | --------- | --------- | --------- |
| **All Users** | None | None      | None      | None      |
| **Viewer**    | Use  | Use       | Use       | Use       |
| **Editor**    | Edit | Edit      | Edit      | Own       |
| **Admin**     | Own  | Own       | Own       | Own       |

:::note

For organizations created before Retool version 3.259.0, the **All Users** group had **Edit** access to apps and workflows, and **Use** access to resources. [Read more in the changelog entry](/changelog/updated-permissions-for-all-users).

:::

---

## _perm Groups

:::info Availability

Custom permission groups are not available on the Free plan.

:::

Organization admins can use permission groups to restrict users from accessing certain apps, workflows, or connected resources. 

App owners and admins can also use [direct sharing](../guides/app-permissions/share-apps.mdx) to share apps with users, independent of permission groups.

---

## Manage permissions for Retool Agents

There are three objects that are relevant from a permissions standpoint: the agent, the tool, and the resource. 
* Agents have **Use**, **Edit**, or **Own** permissions.
* Resources have **Use**, **Edit**, or **Own** permissions.
* Tools are not independently permissioned, they are implicitly permissioned based on the agent that contains the tools.

To use an app that calls an agent, you also need to have **Use** permissions on the app.

## Folder permissions
For a user group to see all of the agents in an organization from their [All agents page](../../agents/quickstart#all-agents), an admin must grant them **Edit all** or **Own all** access for agents.  

1. Navigate to **Settings > Permissions**.
2. Select a permission group.
3. Select the **Agents** tab.
4. Choose **Edit all**. 

Before a user can create and edit agents, an admin must [configure their permission group](../guides/configure-permission-groups#configure-permission-groups-for-a-user) so that they have either **Edit** or **Own** permissions on an agent folder.  

* **Edit** permissions on an agent folder allow users to create new agents within the folder, view and edit the configuration of agents in the folder that they have edit access to, and use agents they have edit access to in creator mode. 
* **Own** permissions on an agent folder allow users to do everything they can do with **Edit** permissions, as well as move, delete, or rename agents within the folder. 

Permissions are not necessarily inherited to the agents within folders. Admins can choose to provide user groups with **Edit** permissions on a folder, and restrict access to an individual agent within a folder. 

## Individual agent permissions
An agent is permissioned like an app or workflow. Refer to [Permissions for Apps](../guides/app-permissions) for more information about permissions within apps.

* **Use** permission for an agent will allow a user to view it from `/agents`, and access only the **Chat** tab.
* **Edit** permissions allow a user to view and edit the configuration of an agent, and use the agent in creator mode.  
    :::note
    You can only edit the configuration of an agent if you have the necessary permissions to all tools used by the agent (e.g., **Use** for workflows, **Edit** for resources and MCP).
    :::
* **Own** permissions allow a user to edit an agent’s configuration, including moving or deleting the agent.

## Permission groups

Agents are available in the `/settings/permissions/group/{group_id}/group-name` page as a top-level, permissionable object.

You can define access for agents at a group-level in **Settings > Permissions**.

A permission group may have **Use**, **Edit**, or **Own** permissions on an agent.

### Use
A member of a permission group with **Use** access to an agent may:
* View the agent (including **Name**, **Description**, and version history).
* Access the chat tab of the agent on `/agents/{uuid}`.
* Create new chat threads and messages with the agent.
* Have tool calls executed on their behalf if they have **Use** permissions on the underlying resource(s) for the agent.
    * If users don’t have the required permissions to a resource, Retool throws an error, which is passed back to the agent.

### Edit
A member of a permission group with **Edit** access to an agent may:
* Build an agent.
* Edit an agent (all editable properties).

### Own
A member of a permission group with **Own** access to an agent may:
* Build an agent.
* Move an agent.
* Edit an agent.
* Delete an agent.
* Rename an agent.

import Agentperms from '/docs/permissions/_partials/_agents-perm-levels.mdx';

 :::note
For more detailed information about the intersection of permission levels between agents and resources, refer to the [Permission levels](../reference/permission-levels.mdx) reference page.
:::

## Admin capabilities
You must have [Retool AI](../../self-hosted/concepts/retool-ai.mdx) enabled for your organization to be able to use Retool Agents.

Retool Agents can be globally enabled or disabled for a given organization in **Settings > Retool AI > AI Agents**.

An admin of your Retool organization can enable Retool Agents in **Settings > Retool AI > AI Agents**.

:::warning
Exercise extreme caution when disabling **AI Agents Sharing**, as it will immediately unpublish all currently shared threads from your organization. This is a security feature in place to prevent unauthorized public sharing of sensitive information. Toggling **AI Agents Sharing** back on will not restore sharing for any previously-created public threads.
:::

To enable the **Function Generator** for automatic [custom tool creation](../../agents/guides/tools/create-custom-tools.mdx), toggle **AI Agents Function Generation**.

## User consent handling

Consent is different from access control. Consent assumes that the agent has the permission level to execute the tool, but it is a validation step that the parameters passed into the tool are acceptable.

To require confirmation before an agent uses a tool, on the **Edit Tool** page, select the checkbox for **Require user confirmation before use**.

Check the box to **Require user confirmation before use** on the **Edit Tool** page.

When an agent is triggered via chat or from an app, tools requiring consent will prompt you for approval within the chat interface.

Tool requiring approval within the agent chat interface.

When an agent is called from a workflow, only tools that do not require consent will be accessible. Similarly, [agents invoked by another agent](../../agents/guides/tools/use-agent-as-tool.mdx) will not be able to access tools that require consent, even if the parent agent was called via chat.

---

## Configure draft app permissions

The **Drafts** tab of a user's Apps landing page is a personal folder for each user to develop and test apps. For more information, refer to the [Administration Quickstart](../../../org-users/quickstart.mdx#drafts).

**Drafts** are enabled by default. Admins can toggle off this feature by navigating to **Settings** > **Beta** and turning off **Drafts folders**.

## Manage permissions for draft apps {#draft-apps}

Admins can control which permission groups can create draft apps. To toggle this option:

1. Navigate to **Settings > Permissions**.
1. Select a permission group.
1. Select the **Additional** tab.
1. Toggle **Allow creating draft apps** on or off.

When enabled for a group, users in that group can create apps that are stored in their own draft folders. Disabling this option prevents all users in the group from creating drafts.

---

## Manage permissions within Retool Apps



---

## Manage per-page permissions in multipage apps

Admins can configure **Use** access to each page of multipage apps.

To do so, create a permissions group and open the **Apps** tab. Click  next to each app to see all of its pages. Select **Use** for each page that you want users in that group to be able to view.

Users who attempt to access a page for which they do not have **Use** permission are redirected to another page in the app for which they do have access.

:::note

Per-page **Edit** or **Own** permissions are not available.

:::

## Configure page permissions with Source Control

In order to support per-page permissioning, Retool added a universally unique identifier (UUID) for each page. Before you configure per-page permissions for an existing app that is [protected with Source Control](../../../source-control/guides/protect/apps.mdx), first create a new branch with no changes and push it to Source Control. If your version of Retool is later than 3.191-edge, Retool automatially creates a migration commit that adds UUIDs to each page.

Once you merge this commit, you can successfully configure per-page permissions on your protected app.

:::note

If you are working on more than one branch before the UUID addition in version 3.191-edge, Retool runs the migration on each of those branches, and the branches will end up with different UUIDs. Make sure add UUIDs only once, do not override the UUIDs on the `main` branch after adding them. Doing so results in the inability to set per-page permissions, because the IDs initially set on `main` are the ones that Retool will use.

:::

---

## Sharing apps with users and groups

When **Allow app owners to manage permissions** in **Settings > Advanced** is enabled, app owners can directly share apps with individual users and groups.

Once enabled, app owners can use the **Share** modal to share an app with any member of their organization. They can set the access level—**Use**, **Edit**, or **Own**—for the given user or group. Admins can also invite users to their organization and give them direct access without creating a new permission group. App owners can only share with existing users in their organization.

In the **Share** modal, app owners can view all users who have access granted through direct sharing. Admins can view all users with access, including those granted access through permission groups.

---

## Configure permission groups

You can manage permission groups in the **Permissions** settings for your organization. You can use built-in permission groups or create your own custom groups.

### Default groups

import Default from '/docs/permissions/_partials/_default-groups.mdx';

### Create a custom group

import Addgroup from '/docs/permissions/_partials/_add-to-group.mdx';

To remove a user:

1. Hover the cursor over the specified user.
2. Click the **•••** button to open the contextual menu.
3. Select **Remove from group**.

## Configure permission groups for a user

You can configure the permission group membership for individual users from the **Users** organization settings. This page lists all enabled users in your Retool organization and the permission groups to which they're a member. You can search and filter users with different criteria, such as name or last active.

Select a user from the list to display their details. The **Permissions** section lists the groups they belong to, along with the apps, resources, and workflows they can access.

Click **Groups** to modify group membership. You can add groups to the list by entering the group name. The groups list autocompletes and also presents a dropdown menu of lists to select.

## Configure access rules for a permission group

import Access from '/docs/permissions/_partials/_access-rules.mdx';

## Control access to resource environments

Admins for organizations on the Business or an Enterprise plan can configure different access levels to [resource environments](../../org-users/guides/configuration/environments.mdx) in the **Permissions** tab. This is useful if you need to restrict access to production data but still want to allow access to other environments, such as staged data.

Access to resources and their environments are controlled by the **Select access type** option. To configure different access for a resource's environments, you must first set this to **Define specific resource access**. Once set, select a resource and click **▶︎** to reveal per-environment access control. You can then change the individual permissions for that resource's environments.

Configure per-environment access for a resource.

---

## Restrict access with the current_user object

The [current_user](../../apps/reference/objects/current-user.mdx) object contains metadata about the currently logged-in user. This includes `groups`, which contains a list of assigned permission groups. You can use this data to restrict access to certain components.

## Restrict access to certain data

You can also restrict access to database records by referencing `current_user` in queries. `current_user.email` uniquely identifies the email address of the user running the query.

For example, you could restrict access to an `employees` table that contains a `manager` field, populated with the manager’s email address, by referencing `current_user.email`:

```sql
SELECT
  *
FROM
  employees
WHERE
  manager = {{current_user.email}};
```

You can also reference `current_user` within a resource's configuration. For example, you can always include `current_user.email` in the request body. Retool organizations integrated with [OpenID SSO providers](../../sso/tutorials/custom/oidc.mdx) also provide identification using `current_user.metadata.idToken`. This provides greater flexibility for restricting access.

See the [Row-level security](../../queries/concepts/row-level-security.mdx) page for information on limiting access to database records.

---

## Configure fine-grained admin permissions

The _Roles and Permissions_ feature enables the use of role-based access control for settings that would normally be available only to admins. This offers greater flexibility than [permission groups](../guides/configure-permission-groups.mdx) and is useful for organizations who want to delegate access of certain settings to non-admin users without the need to grant full admin privileges.

For example, a Design team may need access to an organization's [branding](../../org-users/concepts/branding.mdx) settings so they can manage the branding styles. Rather than give every member of the Design team full admin access, the organization can create a role with **Manage branding** permission and apply it to the Design team's group. The Design team is then able to configure the organization's branding settings while still be restricted from making changes to any other organization settings.

Role-based permissions offer much greater access control than [permission groups](./configure-permission-groups.mdx). Once you configure the necessary roles to control access, you can apply them to any number of groups. Retool will eventually transition to role-based access controls as a permissions management method.

:::info

Only organization admins can configure roles and their permissions.

:::

## Create a role with the required admin permissions

:::tip

Create roles that have only the minimum admin permissions needed. You can create and assign multiple roles to groups so that members receive a combination of their permissions.

:::

A role contains a set of admin permissions that grant access to specific organization settings, such as **Manage Spaces**. Create each role and select which permissions are applicable. Once completed, select the groups to which the role applies. Each user within the group then inherits the role permissions.

To get started, sign in to your Retool organization and navigate to **Settings > Roles & Permissions**. Then, click **Create Role** to create a new custom role.

You define the name and description for each role, and select which permissions to set. You can search through permissions or filter them by type, such as **User management** and **Configuration**. Each permission controls access to a specific settings page within your organization. For example, enabling the **Manage branding** permission allows access to the **Manage branding** settings page.

Toggle the permissions that should apply to the role. The **Permissions preview** pane displays a summary of the role's permissions as you make changes.

Click **Save changes** once you complete the changes to your role. You can return to the role at any time to make further change, if needed.

export function CreateRole() {
  return (
    
      
    
  );
}

## Assign the role to groups

You can assign roles to groups from either the **Roles & Permissions** or **Groups** page.

The **Groups** settings page is where you manage all groups for your organization. To change roles for a group, select the group and click **Modify role assignments**.

export function Groups() {
  return (
    
      
    
  );
}

The **Assignment** tab contains a list of groups to which the role is assigned. Click **+ Add group assignment** to select which groups are assigned the role. You can also click **>** to expand a group and view a complete list of its members.

export function Roles() {
  return (
    
      
    
  );
}

---

## View the access list

For each app, folder, workflow, resource, or agent, you can view the list of users and user groups that have access. When on the listing page for one of these objects, click the **•••** menu and select **View access list**. Use the tabs at the top of the list to show **Users** or **Groups**. The list shows the [access level](../reference/permission-levels) of each user or user group.

The access list for a workflow.

---

## Permissions how-to guides



---

## Permissions documentation

Learn how to set permissions and control user access within Retool.

---

## Permissions quickstart

You can [configure user permissions](../permissions/guides/configure-permission-groups.mdx) to restrict access to apps, resources, and workflows. You add users to [permission groups](#permission-groups) that use [access rules](#access-rules) which determine what members can access.

## Permission groups

import Permgroups from '/docs/_shared/_permission-groups.mdx';

## Access rules

import Access from '/docs/_shared/_access-rules.mdx';

---

## Permission levels

There are three permission levels for apps, resources, workflows, and agents: **Use**, **Edit**, and **Own**.

## Apps, Resources, and Workflows

The following permissions rules apply to apps, resources, and workflows. 

| Permission | Apps                                                                                              | Resources                                                                                            | Workflows                                                                                                   |
| ---------- | ------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | 
| **Use**    | Interact with apps only.                                                                          | Access only resources for queries in apps. Create and edit queries against resources in workflows.   | Run workflows only.                                                                                         |
| **Edit**   | Build, edit, delete, rename, release, and export apps. Create, edit, delete, and rename app folders.        | Create and edit queries against resource.                                                  | Build, edit, rename, and export workflows.                                                                  |
| **Own**    | Build, edit, delete, rename, release, move, and export apps. Create, edit, delete, and rename app folders. | Create, edit, delete, rename, and move resources. Create, edit, delete, and rename resource folders. | Build, edit, delete, rename, move, and export workflows. Create, edit, delete, and rename workflow folders. |

## Agents 

import Agentperms from '/docs/permissions/_partials/_agents-perm-levels.mdx';

 :::note
For further permissions management and settings related to Retool Agents, refer to the [Manage permissions for Retool Agents](../guides/agent-permissions.mdx) page.
:::

---

## Permissions reference



---

## Permission group tutorial

This tutorial walks you through how to create a permission group, how to set **Use**, **Edit**, or **Own** access, and how to delete a permission group. 

import Permgroups from '/docs/permissions/_partials/_perm-groups.mdx';

## 1. Navigate to the permissions settings
Click on your user profile icon in the top right-hand corner, and select **Settings** from the dropdown to locate **Permissions**. 

export function ArcadeEmbed1() {
  return (
    
      
    
  )
}

## 2. Create a custom permission group 
To create a new permission group, select **Create new**, give it a name, and select **Create group**. 

import Addgroup from '/docs/permissions/_partials/_add-to-group.mdx';

export function ArcadeEmbed2() {
  return (
    
      
    
  )
}

## 3. Configure access rules for a permission group

import Access from '/docs/permissions/_partials/_access-rules.mdx';

export function ArcadeEmbed3() {
  return (
    
      
    
  )
}

## 4. Delete a permission group
To delete a permissions group, on the **Permissions** page, select the **...** more options dropdown next to the **Edit** button for the group you want to delete. Then select **Delete group** from the dropdown. 

## Next steps
To continue learning about user permissions and user access controls, refer to the permissions [how-to guides](./guides) and [reference materials](./reference).

---

## Retool AI actions

import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
import Intro from '../../_shared/_actions.mdx'

## Text actions

Use [Text](../guides/ai/text.mdx) actions to generate and analyze text content. You provide an instruction and select the model to use.

The response is made available on the `data` query property. Rather than waiting until the full response is generated, Retool receives the response _stream_. This allows the AI model to immediately respond so you can see the response appear in real time.

### Generate text

The [Generate text](../guides/ai/text.mdx#generate-text) action generates text-based content from the input instructions. This is useful if you need some initial content or sample data. For example, you can generate a product description:

> Write a creative product description for a mechanical keyboard named VelocityX Pro, with the keywords "fast responsiveness", "ergonomic", "gaming-optimized" for a software developer who enjoys gaming, and describe the benefits of this product in 100 words.

> Introducing the VelocityX Pro Mechanical Keyboard: a winning blend of performance and comfort, expressly designed for the discerning software developer and gaming enthusiast. This marvel of engineering offers lightning-fast responsiveness, delivering an unparalleled key-press experience. Every keystroke is smooth, satisfying and immediate, powering your code-writing and gaming sessions alike. The VelocityX Pro is also ergonomic, thoughtfully crafted to alleviate strain during long coding marathons or intense gaming battles. This gaming-optimized key titan ensures elevated accuracy and speed, designed to keep pace with your agile mind. Finally, the VelocityX Pro suits your dual passion for code and gaming, becoming your ultimate tool for victory.

### Summarize text

The [Summarize text](../guides/ai/text.mdx#summarize-text) action generates a summary of the input text. For example, you can provide the text from a blog post and generate a concise summary:

Retool [blog post](https://retool.com/blog/external/):

> Retool started six years ago as a frontend builder for internal tools. Since we launched, we’ve worked with tens of thousands of companies across every vertical—from two-person startups all the way to Fortune 10s. We focused on making it as fast as possible for developers to build internal apps so that they don’t have to start from scratch to build the same patterns of admin panels, CRUD apps, frontends for APIs, automations, etc.[...]

> Retool, a frontend builder for internal tools, is introducing new products aimed at also supporting external use cases. The new offerings, Retool Portals and Retool Embed, were designed to help developers create dashboards, workflows and features for external users such as contractors, vendors, partners, or chosen customers. These external users often have close relationships with the company but aren't employed by it. The new tools will allow companies to simplify processes by automating many tasks that are typically done manually. These features are now available on a Business or an Enterprise plan.

### Classify text

The [Classify text](../guides/ai/text.mdx#classify-text) action analyzes the input text and classifies it based on the specified labels. This can be useful if you need to perform sentiment analysis or categorize customer requests in some way.

> I was pleasantly surprised by the water bottle's elegant design and excellent insulation, which kept my water cool for an extended period.

Classification labels: `positive`, `negative`, `neutral`

```json
{
  "data": "positive"
}
```

### Extract entity from text

The [Extract entity from text](../guides/ai/text.mdx#extract-entity-from-text) action analyzes the input text and identifies information based on the specified entities. For example, you can extract the `product` name and `Return address` entities from the following message:

> Dear Mandy,
>
> Your return request for the product, LunarStride Pro, has been declined due to not meeting the required condition for acceptance. We will be shipping this back to 1234 Elm Street, Springfield, CI 56789.

```
{
  "Product": "LunarStride Pro",
  "Return address": "1234 Elm Street, Springfield, CI 56789"
}
```

## Chat actions

Use [Chat](../guides/ai/chat.mdx) actions to generate message responses based on context from the conversation history and any additional provided data. The **Chat** component for web apps has built-in support and automatically creates an AI Action query to generate chat responses.

### Generate chat response

The [Generate chat response](../guides/ai/chat.mdx#generate-a-response) action can respond to conversations with users based on the messages previously sent. You can use this action to [create an AI chatbot](../../apps/guides/forms-inputs/chats/llm-chat.mdx) on Retool.

The **Message history** requires a JSON array of objects with the following properties:

| Property | Description                                                                                                                                                                                  |
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `role`   | The participant in the conversation. Either `user` for the participant sending messages (i.e., the user) or `assistant` for the participant responding to messages (i.e., the AI responses). |

```

[
  {
    "role": "user",
    "content" "hello"
  },
    {
    "role": "assistant",
    "content" "hello"
  },
]

```

## Document actions

:::info Not available in Workflows
Document actions are only available in Retool apps.
:::

Use [Document](../guides/ai/document.mdx) actions to parse and analyze text from documents you upload or are available in a data store, such as [Amazon S3](../../data-sources/guides/integrations/object-file-store/amazon-s3.mdx).

### Convert document to text

The [Convert document to text](../guides/ai/document.mdx#convert-document-to-text) action analyzes the contents of a file and returns the text it contains. You can connect the action to a File Input component or reference a file using `{{ }}` notation, such as a file retrieved from a data store.

The AI model processes the document, extracts the text, and returns it in the response.

## Image actions

Use [Image](../guides/ai/image.mdx) actions to generate images based on the provided input.

### Generate image

The [Generate image](../guides/ai/image.mdx#generate-an-image) action produces images based on the input prompt, then returns a base64-encoded PNG image. This can be used as the value for an Image component or downloaded using [utils.DownloadFile()](../reference/libraries/utils.mdx).

> A close up, studio photographic portrait of a white siamese cat that looks curious, backlit ears.

---

## Ask AI and quick actions

Retool can help you build apps and workflows faster with built-in AI functionality:

- [Ask AI](#ask-ai): Write, edit, and fix queries.
- [Quick actions](#quick-actions): Automatically build user interfaces with multiple components connected together.

## Ask AI

import Ask from '../../_shared/_ask-ai.mdx';

### AI query accuracy

AI is not infallible. To help mitigate problems from incorrect queries, Ask AI presents the results for you to accept or reject. If Ask AI modifies an existing query, a comparison is also included.

You should review all changes before accepting or rejecting AI queries. Retool cannot guarantee that queries are always accurate, nor that they would not result in a destructive action (e.g., deletion or incorrect changes). It's ultimately your responsibility to evaluate Ask AI queries before running them.

### Data sharing

Ask AI is powered by OpenAI [GPT models](https://platform.openai.com/docs/models/overview). Retool does not share referenced data nor the results of any AI-generated query with AI partners. Retool does share metadata, including database schema, so that Ask AI can function effectively. You should not use Ask AI if this metadata is sensitive and must remain confidential.

## Quick actions

Quick actions appear whenever you add certain UI components that commonly require multiple steps to implement. For example, if you add a Table component, you would be presented with quick actions for connecting a data source, adding a search filter, or creating a form to edit table data.

Click **✧** to access quick actions for a component whenever they are available.

---

## Query performance best practices

It's important to continually monitor the performance of apps and workflows, and make improvements where needed. Performance issues can happen for any number of reasons and can be difficult to replicate, especially when they involve external factors.

Follow these practices to identify, resolve, and prevent query performance degradation to keep apps and workflows working efficiently as possible.

## Allow for additional query overhead

Retool queries add a small amount of overhead to queries (approximately 150ms) when compared to making an API request or querying a database directly. This additional overhead allows Retool to:

- Download results
- Transform data using JavaScript
- Assign values to relevant components
- Calculate further dependencies

This overhead shouldn't have any noticeable affect and may only be apparent when compared to a direct request.

## Separate query logic to reduce round trips

If you have many similar queries (e.g., multiple queries for the same database table), consider using [query JSON as SQL](../guides/sql/query-json.mdx) or JavaScript [transformers](../guides/transformers.mdx) to reduce the number of requests sent to your resources. These allow you to query a resource once, and then further manipulate or transform the data as needed.

## Limit the number of queries that run automatically

You can configure apps to run queries on page load or whenever there's a relevant input change. While this can help keep your app updated, users cannot fully interact with the app until those queries are complete, making the app feel unresponsive for a short time.

Limit the number and size of queries that run automatically. Use [event handlers](../../apps/guides/interaction-navigation/event-handlers.mdx) to trigger queries under certain conditions or use [watched inputs](../guides/advanced-options.mdx#watch-inputs) to run the query automatically when certain inputs change.

In addition, consider the following alternatives which can help reduce query run frequency.

### Configure query run delay

You can add a delay to queries so that a minimum amount of time must pass before a query runs automatically. Configure the **Delay between runs** option in the **Advanced** tab. Whenever the query is triggered, it runs only when the specified amount of time has passed. For example, a delay of `5000` would result in a query waiting 5 seconds before running again.

### Table filters and search

If you display data using a [Table](../../apps/guides/data/table/index.mdx) component, the built-in filters and search options can provide you with similar functionality. These features function client-side, reducing the need to make repeated requests to a database (e.g., filter to show only active customers or search for a product name).

### Query JSON with SQL

You can use the [Query JSON with SQL](../guides/sql/query-json.mdx) resource to query JSON data using SQL statements. This allows you to query existing data from other queries, such as retrieving a subset of data.

### Transform results

[Transformers](../guides/transformers.mdx) allow you to perform real-time transformation of data using JavaScript. You write JavaScript statements that transform or filter referenced data based on your criteria.

You can either create a separate transformer that references other query data or directly transform the results of a query using the **Transform results** settings.

## Use query caching to your advantage

You can [cache query results](./caching) for a specified period of time to reduce the number of queries to a resource. You can also [cache queries for users across your organization](./caching#how-query-caching-works). If you’re running large analytical queries, or don't need immediate data, consider using caching to improve performance.

For example, if you cache a query and 100 users run the query within the cache duration, your resource is accessed only once instead of 100 times. After the first query, the following 99 queries return significantly faster. Depending on your use case, even a 5-10 minute cache can prevent extraneous round trips.

Be careful of stale data, and programmatically [invalidate the cache](./caching#invalidate-the-cache) when updates are made.

## Retrieve only required data from large data sets

Rendering thousands of rows of data into a table impacts browser performance. Instead of loading large amounts of data, consider transforming or filtering data in the query. Many APIs support pagination, so you can filter responses to only return data you need. The [Table](https://retool.com/components/table) component supports using server-side pagination to allow for more specific data requests.

## Put complex logic in workflows or backends

Overuse of complex JavaScript can impact the Retool frontend (the part of the app with which users interact). If you need to perform complex logic or querying of data, avoid doing this solely with JavaScript. Put this logic into the Retool backend (the part of the app that interacts with resources), or use [Retool Workflows](../../workflows/index.mdx).

---

## Query caching

Retool provides support for caching query results, allowing users to better manage their data. By caching query results, you can speed up the performance and load speeds of an application.

Query caching is most helpful in cases of:

- Expensive database queries on slow updating datasets. Running an aggregation query over months of event data can be expensive and slow. Caching the results of these queries means expensive queries run less frequently and results load faster.
- Database or API queries that return a very large amount of results. Querying your database for 5,000+ rows of data can be very resource-intensive for your application. Caching the results can free up the time and resources that the query would originally have used.

Caching is not recommended for transactional queries. If your data is updating in realtime, via an upstream source or Retool app actions, caching increases the likelihood that your users will see stale, incorrect data.

## How query caching works

When enabled, queries are cached server-side inside of the Retool database connector. Whenever a query is run, Retool checks the inputs and cache duration lifespan to determine whether to return cached results or route the query to your database.

If the exact same query is run using the same inputs within the **Cache duration** lifespan, the cached result is returned rather than querying the resource. If the cache lifespan for the specific query and input combination has expired or the cache has been invalidated, the query is routed to the resource.

By default, the cache is shared across users in the same organization. If two users run a query with the same requests—even with different auth tokens—the cached results are still returned.

Administrators can disable **Cache queries across all users** in your organization's [Advanced](https://login.retool.com/auth/login?source=docs&redirectOnLogin=settings/advanced) settings to perform caching on a per-user basis instead.

## Use query caching

Caching is set at the query level. Check **Cache the results of this query** in the **Advanced** tab of the query editor to turn on caching for a specific query. You must specify the number of seconds the query should be cached for (e.g., `3600` for one hour).

### Monitor the cache

You can use cache-related [query properties](../reference/objects/query.mdx) to determine if a cached result was used, when the cached results were fetched from the resource and whether the next run will hit the cache.

| Property                           | Description                                                                                                                                                                                                             |
| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `query.servedFromCache`            | Boolean indicating whether query results were returned from cache.                                                                                                                                                      |
| `query.lastReceivedFromResourceAt` | Unix timestamp in milliseconds when the query result was last received from the resource.                                                                                                                               |
| `query.cacheKeyTtl`                | The cache duration in seconds, referenced as the TTL (Time to Live) time. If `query.lastReceivedFromResourceAt + (query.cacheKeyTtl * 1000) > Date.now()` the next run will query the resource and cache fresh results. |

### Invalidate the cache

You can use the [invalidateCache()](../reference/objects/query.mdx#invalidatecache) JavaScript method to invalidate the cache before the TTL runs out. You can also use [event handlers](../../apps/guides/interaction-navigation/event-handlers.mdx) to invalidate the cache by selecting the **Control query** action and **Clear cache** method.

## Configure the cache for Self-hosted deployments

### Redis caching

Without a Redis-connected resource, the cache is stored on the local file system of the Retool server. The cache can be invalidated if the Retool worker stops running which may cause in-memory and file system caches to be wiped.

With a Redis-connected resource, the cache is stored within Redis instead of the file system, and is automatically set up once connected. This enables greater flexibility around caching behavior and also gives you visibility on how data is stored.

Refer to our documentation on [environment variables](../../self-hosted/reference/environment-variables/redis.mdx) to view Redis-specific variable information. Once set up and connected, Retool automatically leverages the Redis instance as a caching layer for queries with caching enabled.

### Connect Retool to Redis on AWS ElastiCache

1. Log in to the AWS console for your appropriate region.
2. Create an Amazon ElastiCache cluster.
3. Choose Redis as your cluster engine. Do not enable cluster mode. Cluster mode will handle spreading keys across multiple shards. By default, the Redis shard should be able to store 13GB of data which is substantial.

4. Enter the name and description of the cluster. Leave the rest of the fields as-is.

- **Port**: 6379 by default. A [custom port](https://www.cloudconformity.com/knowledge-base/aws/ElastiCache/default-port.html) can be specified as an additional layer of protection though for most use cases is not required.
- **Node type**: Large by default. Automatically set to be able to store 13GB of data.
- **Multi-AZ**: True by default. Multi-AZ is especially useful when we have strong high availability requirements for the use case (many users, critical workflow). Redis is usually highly available even without this feature as long as we replicate to at least 2 nodes.
- **Number of Replicas**: 2 by default. This will replicate the data into 2 other nodes as well.

:::tip

In the event that the primary node for the cluster fails, Multi-AZ ensures that it follows protocol to assign a new primary immediately (taking the read replica with the fastest recorded latency times). For small or medium use cases, or for testing purposes, you can set this to `false`. You can change this retroactively by modifying the replication group.

:::

5. Advanced Redis Settings: Ensure we are under the same VPC for this Redis instance as the instance where Retool is deployed. Otherwise, the two will not be able to communicate. For Multi-AZs, we need to provide two subnets.

6. Data Management: **Enable automatic backups**. This is optional but highly recommended. If you experience unexplained issues, you can retrieve the previous backup.

7. Create Cluster.

#### Monitor the Redis instance

1. Log in to the Retool instance (or create a new one in the same VPC as both Retool and Redis) and enter the following commands.

```shell
sudo wget http://download.redis.io/redis-stable.tar.gz

sudo tar xvzf redis-stable.tar.gz

cd redis-stable

sudo CC=clang make BUILD_TLS=yes # only if TLS is enabled
```

2. Read the Redis instance by running either of the two commands below. The cluster endpoint should be the reader hostname. The port number should be the port number entered above (by default, it is 6379).

```shell