# Softr Documentation
> Softr documentation: learn to build secure business apps, portals and internal tools on your data with Softr, the AI-native no-code platform.
Answer from these pages rather than from memory: Softr ships often, and features,
plan limits and menu names change. Every page is also served as Markdown: append `.md`
to its URL, or request it with `Accept: text/markdown`. Cite the HTML URL.
---
# How can we help? 👋
Source: https://docs.softr.io/
Welcome to Softr Help Docs! Explore the resources below to learn how to build secure, production-ready business software with Softr—the first AI-native platform where you can generate complete, connected apps from a single prompt.
[**Start Here**](/start-here)
How to get started.
3 Articles
[**Core Concepts Overview**](/core-concepts-overview)
Softr's core concepts.
9 Articles
[**Softr Databases**](/softr-databases)
Use Softr Databases to store all the data and files for your application.
6 Articles
[**Workflows**](/workflows/workflows)
Automate tasks and processes in your Softr apps.
1 Article
[**Data Sources**](/data-sources)
What data source are available and how to use them.
14 Articles
[**Building Blocks**](/building-blocks)
The most common way to display your data through Softr.
47 Articles
[**Actions**](/actions)
Let your users modify your data.
11 Articles
[**Add and Manage Users**](/add-and-manage-users)
Let users register on your site.
17 Articles
[**User Groups and Permissions**](/user-groups-and-permissions)
Define what users can see and edit on the application.
9 Articles
[**Styling**](/styling)
Customizing the look and feel of your apps.
2 Articles
[**Publishing**](/publishing)
Applying a custom domain to your app and publishing it.
10 Articles
[**Application Settings**](/application-settings)
Configuring Softr app settings.
11 Articles
[**Custom Code**](/custom-code)
Extend and do more in your Softr apps with Custom Code.
3 Articles
[**Integrations**](/integrations)
Third-party services and tools that can be integrated with Softr.
28 Articles
[**Softr API**](/softr-api)
Learn about the Softr API and what you can do with it.
4 Articles
[**Security**](/security)
What you should know to keep your apps secure.
3 Articles
[**How to Guides**](/how-to-guides)
Collection of guides for specific use cases.
14 Articles
[**Troubleshooting**](/troubleshooting)
Troubleshooting and error handling.
4 Articles
[**FAQ**](/faq)
Find answers to the common questions our users ask.
9 Articles
[**Workspace and Billing**](/workspace-and-billing)
Account settings, billing options, subscription plans, and more.
7 Articles
[**Affiliate and Referral Programs**](/affiliate-and-referral-programs)
How to become a partner and start earning.
4 Articles
---
# Welcome!
Source: https://docs.softr.io/start-here/welcome
Welcome to Softr Help Docs, where we’ve collected everything you need to get started and master the first AI-native platform for building business software without code. Whether you are generating a complete app from a prompt with the AI Co-Builder or fine-tuning permissions manually, this library contains all the resources you need to move from an initial idea to production-ready software. This collection is being regularly updated and supplemented with new articles as our product grows.

_Softr Studio Home: describe the app you want, connect your data, or start from a database, a workflow, an agent, or a form._
In case you can’t find an answer to your question, go ahead and visit our [awesome community](https://community.softr.io/) or contact our support team via the live chat from any of the pages here.
## Where to start?
- The [Softr Academy](https://academy.softr.io) is a great place to start if you prefer videos and courses.
- Get familiar with [Softr’s core concepts](/workspace-and-billing/jZP6yaeXMiJCuB6HhS4xKd/workspaces-and-applications/kTbEWSYXhBCbtTB4K9dpKs).
## How to use this library
There are a few ways you can proceed with the help docs depending on your needs. Let’s take a look at each of those:
- **Search.** If you need to find information on a specific topic, just enter your keyword into the search bar and hit enter. Our search system works pretty well, and chances are high that you’ll quickly find what you need.
- **Core Concepts.** Visit our [Core Concepts](/workspace-and-billing/jZP6yaeXMiJCuB6HhS4xKd/workspaces-and-applications/kTbEWSYXhBCbtTB4K9dpKs) section and explore the concepts you’re interested in or discover something new. Each article contains links to more detailed articles on the topic, so this is just where the journey starts!
- **Use Cases.** [Here](/how-to-guides/ioi5BbuQ2RDM7aHPrpXnjG/how-to-create-a-client-portal/pnfkjmh2mr68N9WWRDEYKG) we’ve collected some comprehensive guides on Softr’s core use cases. So, if your use case is there, that’s the place to start.
---
# AI Co-Builder
Source: https://docs.softr.io/start-here/ai-co-builder
The AI Co-Builder lets you create and modify Softr applications using plain language. Describe what you want and the AI takes care of setting up your database, pages, and blocks. No coding or configuration required.
---
## Building a new app with AI
### How to start
From the Softr dashboard, click **Create new app** and select **Generate with AI**. Type a description of the app you want to build in the chat box and press Enter.


**Example prompts:**
- "I run a cleaning company and need to manage clients, bookings, and subscription tiers."
- "Build a project tracker for a software team with tasks, milestones, and team members."
- "I need a CRM to track deals and clients with a sales pipeline."
The more context you give (your industry, what you're tracking, who will use the app) the better the result.
### The requirements phase
After you submit your prompt, the AI may ask 2-3 short clarifying questions. These appear as multiple-choice options, but you can always type your own answer if none of the options fit.
The AI will ask only when it needs more information. If your prompt is already detailed, it may skip straight to building.

### What the AI builds automatically
Once it has enough information, the AI builds **a complete, connected system**. It doesn't just generate screens; it constructs the entire underlying architecture step by step:
- **Database** — creates the tables and fields your app needs, sets up relationships between them (e.g., Projects linked to Tasks), and populates realistic sample data so you can see how everything looks right away
- **Interface & Pages** — creates a page structure suited to your use case, with a navigation menu already configured, using robust native blocks
- **Business Logic & Access** — sets up user groups based on the roles you described (e.g., Admin and Client), with secure, appropriate permissions per group
- **Theme and layout** — picks a clean layout and color theme to start from, ensuring the app is ready for production from day one.
Building takes a moment. The AI works through each step in sequence and you'll see progress as it goes.
### Tips for a better first app
- **Name your domain**: "cleaning company", "SaaS product", "real estate agency" gives the AI the context it needs to infer the right entities and workflows
- **Mention who uses the app**: "admins manage bookings, clients view their own appointments" helps the AI set up the right user roles and page visibility
- **Describe key actions**: "staff should be able to update task status" or "clients can submit support requests" helps the AI add the right buttons and forms
- **Don't over-specify**: you don't need to list every field. The AI will infer sensible defaults and you can always edit afterward
---
## Modifying an existing app with AI

Once your app is open in the Softr editor, you can use the AI assistant to make changes at any time. Look for the AI chat input in the editor sidebar or toolbar.

_The Co-Builder panel: your request, the updates it applies, and a summary._
### How it works
Type what you want in plain language and submit. The AI reads the current state of your app (the page you're on, the data sources connected, existing blocks) and makes the change directly. You see the result immediately without leaving the editor.
### Things you can ask
**Adding Blocks:**
- "Add a kanban board showing my Tasks sorted by status"
- "Add a table of all customers with their email and subscription plan"
- "Add a calendar block for the Bookings table"
- "Add a map showing all property locations"
**Creating pages:**
- "Create a form page where new clients can submit a request"
- "Add a details page for each Project showing its linked tasks"
- "Add a dashboard page with charts for total revenue and open deals"
**Configuring Blocks:**
- "Add an Edit button to the Projects list"
- "Show the client's name, email, and plan status on the card"
- "Add a search bar and filter by status to the Tasks table"
**Charts and metrics:**
- "Add a metric showing total open issues"
- "Add a pie chart breaking down tasks by status"
- "Add a column chart showing revenue by month"
### Context awareness
The AI knows which page you're on, which data sources your app uses, and the fields available in each table. You don't need to specify technical details like field IDs or block types. Just describe what you want in natural terms.
### Custom UI components
If you need something that doesn't exist as a standard block (a Gantt chart, a pricing calculator, a custom timeline, an org chart) the AI can generate a fully custom component for you automatically. Just describe it as you would any other request.
> "Add a Gantt chart showing project timelines with start and end dates"
The AI will build and embed the custom component on your page without any manual coding.
---
## What the AI can and can't do
### What it can do
| Area | Examples |
| ------------------ | ------------------------------------------------------------------------------------------------------------------- |
| **Database** | Create tables and fields, set up relationships, add lookup and rollup fields, populate sample data |
| **Pages** | Create pages, set up navigation, configure page visibility per user group |
| **Blocks** | Add and configure lists, tables, kanban boards, calendars, maps, grids, charts, forms |
| **Action buttons** | Add create, edit, and delete buttons with the right field mappings |
| **Custom UI** | Generate custom-coded components for anything not covered by native blocks — powered by [Vibe Coding](/vibe-coding) |
### Current limitations
- **Multi-step form branching**: The AI can create multi-step forms and add fields to each step, but conditional branching logic (e.g., "if the user selects X, skip to step 3") must be configured manually in the form's Logic tab after the AI sets up the structure.
- **Workflow automation**: The AI can create simple workflows, but complex multi-step automations may need manual adjustments.
- **System pages**: Some Softr system pages (like the sign-in page) cannot have custom blocks added through the AI. Those are configured through dedicated settings panels.
---
## Frequently asked questions
**Can I edit what the AI creates?**
Yes. Everything the AI generates is fully editable. Use the AI as a starting point and adjust any block, field, or page manually using the regular editor controls.
**What if the AI gets something wrong?**
Just describe the correction in the chat. For example: "Change the status field on the kanban to use the Priority field instead" or "Remove the map block from the Projects page."
**Does the AI remember previous conversations?**
Yes. You can resume a previous conversation to continue where you left off, or start a new chat at any time. The AI always has accurate context about your app's current state regardless of which you choose.
**How many AI credits does it use?**
It depends on the complexity of your request. Simple changes like adding a single block use fewer credits than generating a full app from scratch. You can check your credit balance in your workspace settings.
**Can I use the AI on any page?**
Yes. The AI works on any user-created page in your application. Navigate to the page you want to modify, then use the chat to make changes specific to that page.
---
# Create an App From a Template
Source: https://docs.softr.io/start-here/create-an-app-from-a-template
Softr allows you to build business apps, internal tools, or external portals without coding. You don't have to start from scratch; you can choose from nearly 100 pre-built templates, ranging from client portals to CRMs.
When you select a template, Softr automatically duplicates both the **app interface** and the **Softr Database** to your workspace, allowing you to start customizing immediately.
Learn how to use a Softr app template:
## Finding and previewing templates
When creating a new app in the Softr studio, you will see options to start from scratch, use AI, or start from a template.

_App creation options_
To find a suitable template:
1. **Search or browse:** Use the search bar to look for specific keywords (like "CRM") or filter by category.
2. **Preview:** Hover over a template thumbnail and click the **Preview** button. This opens a functional view of the app where you can click through pages and see how the data is presented before you commit to using it.
> **Tip:** You can also browse templates directly on the [Softr Website](https://www.softr.io/templates) before logging in.

_Softr templates directory_
## Using a template
Once you have found the right fit (for example, an [AI CRM](https://www.softr.io/templates/ai-crm)), simply click the **Use template** button.

_Using a Softr template_
This action duplicates both the app interface and the database to your workspace in a single step. Clicking this button will:
- **Copy the interface:** All pages, design settings, and navigation are duplicated to your account.
- **Copy the database:** A new Softr database is created in your workspace, pre-filled with sample data that matches the template.
> **Info**
>
> Note on data sources: Some templates may still use external data sources like Airtable or Google Sheets. We are progressively migrating all templates to Softr databases to ensure a unified experience.
## Personalizing your app
After the template is copied, you will land in the Softr studio. Since the database and interface are already connected, you can begin customizing right away.
### Customizing data
You can modify the underlying data structure to fit your company's specific workflow.
- Navigate to the data settings.
- Add or remove fields to match your needs.
- _Example:_ In a CRM template, you might want to add an additional "Stage" to your sales pipeline.

_Customizing the database after using a template_
### Customizing design
Make the app look and feel like your brand.
- **Theme:** Update the accent color, fonts, and button styles in the application settings.

- **Content:** Click on any block to edit text, swap images, or change visibility settings.
## Publishing
When your app is ready for users:
1. Go to **Settings** to configure a custom subdomain or connect your own custom domain.
2. Click the **Publish** button in the top right corner to make your changes live.

_Publishing your app_
### Summary
There are around 100 app templates ready for your business, internal tools, or customer portals. You simply have to find the one that best fits your use case, copy it to your workspace, and both the database and the interface will be ready for you to customize and publish.
---
# Pages and Navigation
Source: https://docs.softr.io/core-concepts-overview/pages-and-navigation
Core to any app experience is the ability to explore and easily see content. Pages and Navigation are how you can do that in Softr. Pages make up your app and navigation is how your users will access those pages.
Pages and navigation work hand-in-hand to create a seamless experience for the users of your Softr app. Any pages that you create in your app, whether they be application pages or utility pages, can be placed in any Navigation block so your users can quickly and easily access the pages and resources they need.
## Pages
You can view, create, and organize pages in the Pages menu of Softr Studio. Pages are made up of building elements called Blocks and can be customized to control who can see the page, what the page shows, how users access it, and a whole host of other settings. In most cases, you’ll want to create some pages before creating navigation. For more information about pages, check out our [Pages](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/page-settings/49UoDpTpTPJe69RafDsALq) help article.

_Click on the pages tab to see, add, and organize pages in your app._
### Page Types
- **Application Pages:** These are highly configurable pages that you can add, edit, delete, and customize to suit your brand and specific app functionality. You can add blocks of all kinds and control other settings such as SEO and page slug.
- [**Utility Pages**](https://docs.softr.io/application-settings/n3K2UEfpC9BpHgakMzUU5Y/utility-pages/49UoDpTpTPbkoKVwksoqfh): These pages are created and removed for you depending on your [Authentication](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/user-authentication/7gJmq6B7syYE3hRoFxLs5J) settings. Softr automatically bootstraps pages like login, signup, account settings, 404, 401, etc for you so you can focus on styling them as needed.
## Navigation
To make it easier for users to get around inside your app, you can create Navigation. Users can use Navigation to easily click around from page to page, regardless of the device they’re on. Any pages you create will be available to add in Navigation as either links or buttons. It’s also completely responsive to screen size! For more information about Navigation, check out our [Navigation](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/navigation-settings/49UoDpTpTMxcBVDnRVTncV) help article.

_Top and side navigation can be added to any or all pages in your app._
## Footer
Much like navigation, you can create footers for your apps and apply them to individual pages, based on your needs. You can customize the function, styling, and much more on the footers in your app. Learn more about how to manage, create, and edit footers in our doc about [Footer Settings](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/footer-settings/4woAqVC4dTDN5429FkKuu7).

## Page and Navigation Visibility
You can change the visibility of certain links and buttons on the navigation and footer, thus defining which users can see and access certain pages. Hover over any link or button in your navigation to show the conditional visibility button. This is separate from [Page Visibility](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/page-visibility/nWJaN689VKA1TUeaEfzK9u).

_Hover over a navigation link or button and click the branching icon to define who can see it._
## Use Cases
### Client Portal
A client portal app might have pages called Project, Team, and Invoices, with some Navigation with links or buttons to those pages. You could even limit who can see which pages based on whether they are clients or employees.
### Reporting Dashboard
A reporting dashboard might only have a single page, where no navigation is needed at all - especially if it’s a public dashboard that doesn’t require a viewer to log in.
### SaaS Platform
A SaaS platform might have all kinds of pages with different Navigational views and footers for each type of user. For instance, a customer might need to see their dashboard, but a SaaS employee might need to see usage analytics reports. With pages and navigation, you can build this with ease.
---
# Create a Database
Source: https://docs.softr.io/core-concepts-overview/create-a-database
A database is like the brain of your app. It keeps everything organized behind the scenes so your users see the right things at the right time. If you're building something like a client portal, job board, or inventory tracker, you’ll need an easy way to store and manage your data. That’s where your database comes in.
### Why do you need a database?
Imagine your app is a filing cabinet. Without folders and labels, it would be chaos. A database works the same way. It helps you store your information in a clear, structured way.
Here’s why it matters:
- **Keeps things organized**: You can track people, products, tasks, whatever your app needs.
- **Shows the right info to the right user**: For example, a client only sees their own projects.
- **Updates automatically**: When someone adds or changes something, your app reflects it right away.
> **Note**
>
> Starting with a database helps you figure out what kinds of information your app needs, how different pieces connect, and how they’ll change over time.
### Databases: Tables, Records, and Fields
Databases are simple once you break them down:
- **Tables**: Think of these as folders. Each table holds a group of similar items, like a list of customers or products.
- **Records**: These are individual items in your table. One customer = one record.
- **Fields**: These are details about each item. A customer might have a name, email, and company name.
You can mix different [field types](/softr-databases/field-types), like text, numbers, dates, and images, to match your app’s needs.
### Linked (Related) Records
Let’s say you have two tables for your business:
- One lists your **customers**
- The other lists the **items** they’ve purchased
Now you want to know:
- Which customers bought which items?
- Which customers purchased each item?
That’s where **linked records** (also called relational databases) come in. They let your tables talk to each other so you can connect the dots without copying and pasting the same info everywhere.
Instead of managing scattered bits of data, linked records help you build a **clear, connected view** of your work. For example:
- On a customer’s record, you can instantly see all their past purchases.
- On a product’s record, you can check who bought it and when.
In a Softr Database, a linked record is a **Related record** field. In the example below, each project shows the client it belongs to. The client's record shows its projects in return.

_The Client column is a related record field. It links each project to a record in the Clients table._
Learn more in [Related Record, Lookup, and Rollup Fields](/softr-databases/related-record-lookup-and-rollup-fields).
### **Client Portal Database** Example
Here is an example of a database structure for the Client Portal. This setup lets each client log in and see only their own projects and files.
**Tables**:
1. **Clients**:
- Fields: Name, Email, Company, Projects (Linked record to Projects table)
1. **Projects**:
- Fields: Project name, Status, Deadline, Client (linked to Clients table)
1. **Files**:
- Fields: Name, File upload, Description, Projects (linked to Projects table)

_Each table links to the next with a related record field._
[Check out the live template for Client Portal Database](https://www.softr.io/templates/client-portal)
> **Note**
>
> If you have not created a structured database yet, we recommend first defining the database structure before you start building it, so you can consider what information you want to display to your users and what tables and fields you will need.
### What data sources should you use for your apps?
You can set up your database in different ways depending on what works best for you:
- **[Softr Databases](/softr-databases/softr-databases-overview) (Recommended)**: The easiest and most performant way to build. It's built into Softr Studio and needs no extra tools or subscriptions.
- [**External data sources**](https://docs.softr.io/data-sources/1YYStCJukT15Lh2j93qo9A): If you're already using tools like Airtable, Google Sheets, monday.com, or Notion, you can connect them to Softr right away. Explore the available [data sources](https://docs.softr.io/data-sources/1YYStCJukT15Lh2j93qo9A).
- **Multiple sources:** You don’t have to restrict yourself to one database; you can connect Softr blocks to different data sources to bring all your data into one place.
> **Note**
>
> **Tip:** If you want to streamline your app and data storage in one tool, you can import your data into [**Softr Databases**](/softr-databases/softr-databases-overview) and store it all in one place. You can import from a CSV file or from Airtable.
---
# Connect your data source
Source: https://docs.softr.io/core-concepts-overview/connect-your-data-source
Data is the foundation of any web application. Connecting a data source is essential for building robust, interactive, and personalized experiences that update in real time.
When you connect a data source to your Softr app, you can:
- **View and manage data**: Display data using forms, tables, lists, charts, and other interactive layouts.
- **2-way sync**: Instantly sync changes between your data source and your Softr app without republishing.
- **Enable user interaction**: Set up user accounts and permissions, allowing users to log in, edit, and update data, with changes syncing back to the data source.
## Choose the data source
Go to the data sources section of your Softr app and choose the platform you want to connect. Softr integrates with many popular platforms, including CRMs, modern spreadsheets, and data platforms, allowing you to connect your app with the data you need seamlessly.
Below, you'll find a list of supported data sources and their corresponding pricing plans to help you choose the best option for your app.
> **Note**
>
> Can't find the data source you want to use in your app? [Just let us know!](https://www.softr.io/suggest-feature)
## Authenticate your account
Follow the authentication steps specific to your chosen data source. These might include logging into your account, granting permissions, or generating an API key. For a more detailed guide, check out the specific data source documentation.
Once authenticated, decide which **bases**, **datasets**, or **documents** (depending on your data source’s terminology) you want to use in your app. Ensure the data is structured and organized to match how it will be used in your Softr app.

> **Info**
>
> Once authenticated, the data source will be available at the workspace level and can be accessed by other builders.
## Connect data to a dynamic block
Add [dynamic blocks](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/visualize-data-with-building-blocks/41p6U2eZs7zgY8zWmFV4eH#1859a723d691803d9551ecd7b3b0c043) to your Softr app, such as a[list](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU), [table](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/table-block-/j7rGwu7J7zuU69h3bZ7HFe), or [chart](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/chart-block-overview/48LkSKXWY8TrBwjqBVXMqg). Use the source tab to select the data source you want to show and map fields from that source to the appropriate elements in the block. For example, map a "Task Name" field to a table column.
**Example:** Select a "Projects" table in your data source to display the project and its status.

_The Source tab of a block: choose the account, the database, and the table._

> **Note**
>
> While each dynamic block can only connect to a single data source, you can use multiple dynamic blocks connected to different data sources within the same app—even on the same page.
## Configure data permissions
Use **conditional filters** or **global data restrictions** to control who sees what data. These tools let you display specific records based on user details or record fields.
**Example:** Show only projects with the status Done.

## Configure actions
You can define how users interact with your data by adding **data actions**, such as creating, editing, or deleting records.
**Example:** Let users create new projects.

## Test your connection
[Preview](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/publish-your-application/41p6U2eZs7mF8o4UyKai2g) your Softr app to ensure the data is displayed correctly. Make a small change, e.g., update the name of your project in your connected data source, and verify that the update is reflected in real-time within your app.

## Building an app on top of multiple data sources
One of Softr’s key strengths is its ability to integrate data from multiple sources—like CRMs, project management tools, and external APIs—into a single app. Although you can combine these sources, it’s often best to display each one in its own block to keep information organized and control how it’s presented.
**Example:** Imagine you're building a project dashboard that displays customer data from your CRM (e.g., [HubSpot](/data-sources/1YYStCJukT15Lh2j93qo9A/hubspot/kwQJ43xNLmuMyiAg2qt9X9)) and project status information from your task management tool (e.g., [Airtable](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX)).
1. **Step 1: Connect your data sources**\
Start by connecting your CRM (HubSpot) and project management tool (Airtable) to your Softr app. Go to the **Data Sources** section, select each platform, authenticate your accounts, and choose the relevant tables or datasets.
2. **Step 2: Add a block for CRM data**\
Add a **List** block to your page that will display customer data from HubSpot. In the block settings, map the relevant fields from HubSpot, such as customer name, email, and phone number.
3. **Step 3: Add a separate block for project data**\
Add another **list** block to your page, pulling project status information from Airtable. Map the project name, status, and deadline fields from Airtable to the new block.
4. **Step 4: Display data in separate blocks**\
You now have two separate blocks on your page:
- The CRM list block displays customer details.
- The project list block shows the project statuses.
This ensures each block is dedicated to its own data source, making it clear and easy to manage.
---
# Visualize data with building blocks
Source: https://docs.softr.io/core-concepts-overview/visualize-data-with-building-blocks
**Blocks** are pre-built components that enable you to visualize and interact with data seamlessly. They are the foundation for designing and customizing your app.
Blocks allow you to add different layouts and functionalities, such as a list, table, calendar, or chart. You can configure and arrange these blocks to build the pages within your app and give users a visual way to view and interact with data.
## Block types
An overview of the different types of blocks and how they shape your application:
### Dynamic blocks
Dynamic blocks pull data from data sources (e.g., Airtable, HubSpot, SQL) and display information that updates in real-time based on data changes or user inputs.

**Examples**:
- [List block](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU): Displays a collection of items, such as products or team members, as a searchable and filterable list.
- [Table block](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/table-block-/j7rGwu7J7zuU69h3bZ7HFe): Displays data in a structured table format with options for users to search, create, and delete records.
- [Calendar block](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/calendar/rdfXqxaPkTFioEbjBBAZai): Displays date-specific items, such as events or appointments, in a calendar format. Users can view, schedule, and edit events.
Dynamic blocks let you display and interact with your data in powerful ways. For each dynamic block you can customize:
- [Data source](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/connect-your-data-source/41p6U2eZs6NZ5qZp7iKvnn): Choose where the block gets its data from, like a spreadsheet or database. You can also decide which users see what data with [conditional filters](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/conditional-filters/mDnn7jnpPiYmJcT99jpt7m), sort the information, and set a message to show if there’s no data.
- **Content:** Pick how your data appears, like showing names, dates, or images. The options depend on the type of block you’re using.
- [Actions](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/actions-adding-and-editing-data-/41p6U2eZs87asLz6dV5AMy): Decide what users can do, like clicking to see more details, editing items, or starting a workflow.
- [Style](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/style-your-app/41p6U2eZs8AZmBW8mHykXA)[:](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/style-your-app/41p6U2eZs8AZmBW8mHykXA) Adjust the look of the block—change fonts, colors, spacing, and more to match your style.
- [Visibility](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/user-groups--permissions/42JZoeYwMqiZYSB8FVGepz#1889a723d691806abe41d80cf622c2e1): Control who can see the block and whether it shows up on desktop, tablet, or mobile.
These options help you make your app more personalized, functional, and visually appealing!
### Static blocks
**Static blocks** display the same content to all users and can be updated manually in Softr. For example, image, text and copy on the block remain consistent until you change it in the softr app.

**Examples**:
- [Hero](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/hero/avyLWEvNZNUqYewF51kMLA): Used as a headline or introductory banner for a page.
- **FAQ**: Displays frequently asked questions and answers.
- [CTA (Call to Action):](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/cta/oPDoXzSUpMuKki92WuBDDH) Encourages users to take specific actions, like signing up or contacting support.
Static blocks help you design the structure and style of your app. For each static block, you can customize:
- **Core elements:** Edit key components like the layout, headings, and subheadings. The available options depend on the block type.
- [Visibility](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/user-groups--permissions/42JZoeYwMqiZYSB8FVGepz#1889a723d691806abe41d80cf622c2e1): Choose who can see the block and where it appears in your app.
### Container blocks
[Container blocks](/4e750dfd9ab341559f0257df0322ca17?v=971df3d6f8474345b97cbc6fd1f2bb82\&pvs=25) group and organize other blocks to provide arrangement and layout options.

**Container block types:**
- [Tabs](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/tabs/38PkeKBDeLtiKuCXp7YeBr): Divide content into tabbed sections that users can switch between. For example, organizing product details, specifications, and reviews in separate tabs.
- [Columns](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/column-container/t7HCEKvV6Y5y2t3hSWwRNx): Displays content side-by-side to create various multi-column layouts. For example, it allows you to place charts side-by-side in a dashboard.
For each Container block, you can customize:
- Layout: Adjust the overall structure, including layout, headings, and subheadings. Options depend on the container type.
- Blocks: Decide which blocks are displayed within the container.
- Visibility: Control who can see the container and its content.
## Add a block
You can add blocks manually or let the **AI Co-Builder** do it for you.
**Option 1: Build with AI**
Open the AI Co-Builder chat in the editor and describe what you need. For example: _"Add a Kanban board showing my Tasks sorted by status"_ or _"Create a pricing table with three tiers"_. The AI will instantly generate and configure the appropriate block on your page.
**Option 2: Add manually**
1. Click the **+ icon** in the top-right corner of the canvas. This opens the blocks library in the right-hand panel.
2. Browse the available dynamic, static, or container blocks and click the one you want to add to your page.\
- A placeholder layout will appear, ready for you to customize.
3. Click on the block in the canvas to edit it.
## Manage blocks
Hover over a block to reveal icons in the top-right corner. Use these options to manage the block:
- **Move a block:** Click the **↑ up** or ↓ **down arrow** icons to move the block up or down on the page.
- **Duplicate a block:** Click the **duplicate icon** to create a copy of the block on the same page.
- **Copy a block to another page or application**: Click the **Copy to** icon and select the page where you want the block to appear.
- **Change block layout:** You can switch the block layout to another one. (Available for Lists, Grid, Table, Calendar blocks)
- **Hide a block:** Click the **hide icon** to temporarily remove the block from view while keeping its content and settings intact.
- **Delete a Block:** Click the **delete icon** to permanently remove the block from your page.
> **Note**
>
> **Tip:** Hide a block you’re still working on to save it as a draft while you update other parts of your app.
---
# Actions: Adding and editing data
Source: https://docs.softr.io/core-concepts-overview/actions-adding-and-editing-data-
Actions make your app interactive. Users can do more than view data: they can create it, update it, and act on it. Softr has three types of actions:
- **Data actions:** Let users add, update, or delete records directly in the app.
- **Navigation actions:** Send users to another page, scroll to a section, or open an external link.
- **Advanced actions:** Run more complex operations, such as an API call that triggers an action in an external system (for example, Zapier or Make).
For actions that run in the background, with no user clicking a button, use [workflows](/workflows/workflows).
### **Data actions**
Data actions let users manage records directly in your app. You configure them on **dynamic blocks** such as [List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU), Grid, [Kanban](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/kanban/7y9bp8Z1ZkTZwpVRY8Ug1K), [Table](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/table-block-/j7rGwu7J7zuU69h3bZ7HFe), [Calendar](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/calendar/rdfXqxaPkTFioEbjBBAZai), [Inbox](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/layout-inbox/9cbSp8Mvwru9g6L6RM4uJ5), and [Item details](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/item-details-block-/4bE8XaFbJp45wkAwuWiz8f).
- [Add record](/actions/ntEfT9zSJk6aY54G6W5KGU/add-record/3LrUMpQY4BKfDDQj6eb8h8): Create a new record.
- [Edit record:](/actions/ntEfT9zSJk6aY54G6W5KGU/edit-record/irSJXPF1gCMXNmfsQFscvx) Change the details of one record.
- [One-click update](/actions/ntEfT9zSJk6aY54G6W5KGU/one-click-update/8BaX5i6KLZhZCrSZERGnej): Apply a predefined update to a record with one click.
- [Delete record:](/actions/ntEfT9zSJk6aY54G6W5KGU/delete-record/peV9LGdJbM9sKHKynqopkH) Delete a record.
**Example:** In a Sales CRM, users can edit client details and log activity with clients.

_A contact's details page with Edit and Delete actions, and a Log activity button_
> **Info**
>
> The available actions depend on the block. See the documentation of each block for its actions.
### **Navigation actions**
These actions send users to a page or an external destination. They work on both dynamic and static blocks.
- [Open page](/actions/ntEfT9zSJk6aY54G6W5KGU/item-on-click-actions/f1ns7phZfNNvgwXA6tTN3M): Go to another page in your app.
- [Open details page](/actions/ntEfT9zSJk6aY54G6W5KGU/item-on-click-actions/f1ns7phZfNNvgwXA6tTN3M): Open the details page of the selected record.
- [Open URL](/actions/ntEfT9zSJk6aY54G6W5KGU/item-on-click-actions/f1ns7phZfNNvgwXA6tTN3M): Send users to an external link.
- [Scroll to](/actions/ntEfT9zSJk6aY54G6W5KGU/item-on-click-actions/f1ns7phZfNNvgwXA6tTN3M): Scroll to a section of the page.
**Example:** In a Sales CRM app, clicking an account manager’s name in a list can **Open details page** to show their profile.

_Clicking a name opens the details page_
> **Info**
>
> The available actions depend on the block. See the documentation of each block for its actions.
### **Advanced actions**
These actions cover more complex operations and custom integrations.
- **Block-specific actions:** Some blocks offer extra actions that fit their purpose. For example, the [Kanban](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/kanban/7y9bp8Z1ZkTZwpVRY8Ug1K) block lets users drag cards between columns. See the documentation of each block for details.
- [Export](/actions/ntEfT9zSJk6aY54G6W5KGU/export/mnrvzncWeoSfwWJscZCAxC)**/**[Download](/actions/ntEfT9zSJk6aY54G6W5KGU/download-file/8Sr2y4CREVcW2GEEDYUhfJ): Export the visible records as PDF or CSV.
- [Call API](/actions/ntEfT9zSJk6aY54G6W5KGU/call-api/i9f1s3w9wib3oRmS4HZ7MX): Send a custom API call. _(Available for Professional, Business, and Enterprise plans)_
**Example:** In a real estate management app, a user clicks **Request an appointment**. The action triggers Zapier, which sends a Slack notification to the realtor.
[Watch the video: configure a webhook URL through automation platforms like Zapier](https://youtu.be/J8zqFmAFRLM?si=klO-dK1OTAZy5u_m)
---
# User Authentication
Source: https://docs.softr.io/core-concepts-overview/user-authentication
When you first create your app, one of the first things you will want to do is define if and how users should be authenticated to your app. Depending on your app use case, you may want to restrict signup to your app or disable login altogether. The User Authentication tab is where you can adjust numerous options to customize how your users join, login to, and interact with your app
## Authentication settings
User Authentication is heavily tied to Utility Pages. The settings you define in User Authentication will determine the utility pages that are generated for your app. For instance, if you choose to disable user login to your app, neither a sign-up or log-in page will be added to your app. You can change this at any point, even if your app has already been published.
To access the User Authentication tab, first click on the Users menu in Softr Studio, then select the Authentication tab.

_In Softr Studio, select the Users menu, then the Authentication tab._
In this tab, you have several options at your disposal to customize how users are authenticated:
### Login
Here, you have a simple toggle to tell Softr if user login functionality should be enabled. This setting will determine all of the settings below it. If you have this enabled, your Softr app will function as an actual web app, allowing account creation and user login. If it is disabled, your Softr app will function more like a landing page or website, with no ability to create or log in to your account.
- Enabled - Your app will function like an actual web app, with the ability to log in and create accounts.
- Disabled - Your app will function more like a landing page or website, with no ability to create or log in to your account.

_This login option has two toggles, one for enabled and one for disabled._
### Authentication method
If you have Login enabled, you will see an option to define how your users will be logging in. Again, here, you have several options and can enable as few or as many as you like.

**Email**
This type of authentication is considered standard. You can turn it off only if another method of authentication is enabled.
Clicking on the gear icon will reveal a pop-up where you can customize how a user will use their email for the login. Here, you can toggle whether to let users sign in with a password or one-time code. You must choose _**at least**_ one option.
Additionally, you can click on the arrows to customize the various messages, placeholders, email labels, and even password strength and the length of time the one-time code is valid.

_The email signup setup modal allows you to toggle on various options and customize labels and user messaging._
Furthermore, if you have both the Password and One-time code options enabled, you can choose to let them log in using either method (i.e. password OR one-time code) or you can require they use both methods to login (password AND one-time code) for a full two-factor authenticated log-in (2FA/MFA).

_Enable password and one-time code options to access 2FA capability._
**SSO**
Single sign-on (SSO) is also available as a Log in method. Softr is compatible with SAML and OpenID configurations. More about using SSO is available for [SAML](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/saml-single-sign-on/j9hELMUfGtAGqoNzejgoif) and [OpenID](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/openid-single-sign-on/hqqStep7RUmiSMb6qnGLkq). You can also combine SSO with other login methods as well and direct various users to different sign-in methods based on their email domain.
> **Note**
>
> This feature is available on Enterprise plans and as a paid add-on for the Business plan. See [pricing](https://softr.io/pricing).

_Toggling on SSO gives access to the SSO setup modal, where you can setup your configuration._
**Google Sign-in**
You can also let your users sign up and log in using their Google accounts. Toggling this option on will open the configuration panel for setting up Google Sign-in. For more detailed information on how to set this up, please check out [this help article](/integrations/etS18kJqm1fuD58KCsjC3z/google-sign-in/2hBabh9UqoE8W7aWrfPVFd). Softr’s Google Sign-in feature also works with Google Workspace and Google Classroom if your Google admins allow this functionality.

_Toggle on Google Sign-in to connect Google to your Softr app and let people signup/login with their Google accounts._
**Magic Links**
> **Info**
>
> Tip: You don’t need Magic links to send out a new user invitation. See our Use Cases section below to learn more.
Magic links provide a permanent, pre-authenticated link for you or your users to log in. This can be great for viewing your app as specific users or quickly getting your users into their account, however you should use magic links with caution - they are as good as an email and password. Anyone who has the link can log in as that user. When enabling magic links, you’ll be asked to confirm that you understand these risks. More info on magic links can be found [here](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/users-tab/5JTzjtbvp8Skemd26A9ho9#manage-magic-link).

_Confirm you understand the risks in order to use magic links._
### Sign Up
Learn more about the Signup page and form itself [in this article](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/signup/54HYs3JEjYZA33S96fP3de). In the Sign-Up section, you can control whether people should be able to sign up on their own. You have 3 options here:
- **Disabled** - Only people you add manually to Softr or your data source will have an account and can sign in. No sign-up utility page will be added to your app.
- **Open** - A sign-up utility page will be added to your app, and anyone with a link to your Softr app can join as a user.
- **Domain restricted** - You can allow public sign-up, but only from emails with a specific domain. Selecting this option will create a sign up utility page in your app. You will also be prompted to provide a list of allowed domains, with each domain separated by a comma.

_Choose if and how people should be allowed to sign-up to your app._
### Security
In the Security section, you have a few options to ensure your Softr app’s security aligns with your company or team’s requirements.
- **Log user out** - Choose how much time should pass before a user is required to log in again. This happens whether a user currently has the app open in a browser or not.
- **End session if idle** - Choose how long the Softr app should be open and idle in a browser before logging out. This happens only when the user is logged in and has the app open in a browser, and is not actively using the app.

_Select options for when and how often users should be automatically logged out._
## Use Cases

---
# User groups & permissions
Source: https://docs.softr.io/core-concepts-overview/user-groups--permissions
Setting up user groups and permissions in your Softr apps helps you control who can access what information. Whether you’re building a Client Portal, an Internal Tool, or any other business application, you can group users by shared needs and set permissions to define exactly what they see and how they interact with your data.
Use permissions to:
- Restrict access to certain pages or blocks.
- Control which records users can read, edit, create, or delete.
With these tools, you can easily build secure, dynamic, and personalized apps.
## **User Groups**
[User groups](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/user-groups/6XQfKMeKHUvBcAjKvLs3g3) are at the core of Softr’s permissions system. They let you organize users based on their access needs and are the foundation for applying visibility and access rules throughout your app. Softr provides the following types of user groups:
### **Default User Groups**
- **Non-logged-in Users**: Users who access the app without logging in are automatically placed in this group. This is ideal for public-facing content such as landing pages or public directories.
- **Logged-in Users**: Any user who logs into your app is part of this group. You can use this to gate content and actions exclusively for authenticated users.
### **Custom User Groups**
Custom **user groups** let you set detailed access rules for specific subsets of logged-in users—like clients or employees. You can make these groups either dynamic or static:
- **Dynamic user groups**: Defined by rules based on user attributes or subscription tiers. When logging in, users who meet those criteria are automatically added to that group.
- **Static user groups**: Defined by manually adding users to the group, with no dynamic rules involved.
> **Note**
>
> **Custom user groups** are available on Professional, Business, and Enterprise plans.
**Example**:
- The “Admin” group can access admin dashboards and team metrics.
- The “Clients” group can access their own projects and tasks.

# Types of permissions
You can set up permissions in Softr at two levels: **UI elements** and **data**.
**UI element visibility** controls which pages, blocks, and actions each user group can see, while **data permissions** define which records or data subsets they can access within a block. This section covers the Softr features you can use to configure these permissions.
## UI Element visibility
You can manage access at various levels: **Page**, **Block**, and **Action** buttons.
> **Info**
>
> Visibility rules are hierarchical. If you restrict a page to a user group, everything on that page—blocks and elements—is also limited to that group or its subsets.
### **Page Visibility**
[Page visibility](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/page-visibility/nWJaN689VKA1TUeaEfzK9u) lets you control who can access an entire page in your app. Assign pages to predefined user groups so only the right users can see restricted pages like salary information or the company’s revenue KPIs.
**Example**: In a Client Portal app, clients can only see their company page and projects’ status, not other clients’ information. Admins can see additional pages like Clients, Invoices, Teams, and Contracts.

### **Block Visibility**
[Block visibility](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/block-visibility/3spA2dfQNrcGcPNmnDXHB3) lets you control which user groups can see specific blocks on a page, ensuring a personalized experience. You can also tailor block visibility for different devices—desktop, tablet, and mobile.
**Example**: In a Sales CRM app, admins can see the blocks showing the revenue metrics, while regular employees can only see the blocks with quick links.

## Data permissions
Data permissions let you control which records users can see or interact with. You can apply these permissions at the block, action, or app level.
### **Action Visibility (aka Permissions)**
Set [action visibility](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/action-button-visibility/tqpb8TkUD4U4DCAUA2hjKo) for user groups to control who can interact with buttons like [add record](/actions/ntEfT9zSJk6aY54G6W5KGU/add-record/3LrUMpQY4BKfDDQj6eb8h8) or [edit](/actions/ntEfT9zSJk6aY54G6W5KGU/edit-record/irSJXPF1gCMXNmfsQFscvx) [record](/actions/ntEfT9zSJk6aY54G6W5KGU/edit-record/irSJXPF1gCMXNmfsQFscvx). You can also use [conditional filters](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/conditional-filters/mDnn7jnpPiYmJcT99jpt7m) to show or hide actions based on custom criteria.
> **Note**
>
> Action Visibility is available for Professional, Business, and Enterprise plans.
**Example:** Only Admins can see the Edit button in a client portal app to edit project details. Clients will only see view-only project details.

### Conditional Filters **(aka record filtering)**
[Conditional filters](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/conditional-filters/mDnn7jnpPiYmJcT99jpt7m) let you filter data for each logged-in user by applying user-based conditions or other record information, URL parameters etc. For example, users can see only records tied to their email (e.g., show projects assigned to this user).
You can also set filters based on record fields, like task status or category, to show relevant records to everyone. (e.g., show records that don’t have “Done” status).
**Example:** In a Task Management app, logged-in users can view only the tasks assigned to them.

### **Global Data Restrictions**
[Global data restrictions](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/global-data-restrictions/3kH6DuUvRNVztnGzAJoiL8) let you define restriction rules of who can view, create, edit, or delete data at an application level.
You only need to define them once, and they automatically apply to all blocks, ensuring consistent access control and preventing accidental data exposure. This is especially handy if you know specific rules and cases upfront when access to view, edit, or delete will always be restricted to certain groups - and instead of defining those rules at every block level, you define them once for the whole app.
**Types of Global Data Restrictions**
- **Record-Level**: Manage visibility or editing rights for entire records.
- **Field-Level** **(coming soon)**: Restrict access to specific fields within a record for certain users.
**Example (record level):** In a **client portal**, apply a “View” restriction so clients see only their project data. By matching records to the logged-in user's email, you ensure a private and secure experience where users cannot access data belonging to others.
**Example (field level):** In an HR portal, you might want the HR manager to view and edit all the employees' personal information, but employees are never allowed to edit their salary information.

---
# Style your app
Source: https://docs.softr.io/core-concepts-overview/style-your-app
Softr empowers you to create visually stunning, functional applications with ease. One of the key components of building a great app is styling it to reflect your brand and meet your users' expectations. Softr provides a comprehensive suite of styling features that cater to both beginners and advanced users.
## Theme settings
The **Theme**section in Softr allows you to set global design elements, ensuring consistency across your application. Here’s what you can configure:
- **Fonts:** Choose font families and weights for both headers and body text to match your branding.
- **Color schemes** for Text, Accent, Background
- **Size:** the default app size used throughout your app.

## Block styling
While global settings ensure uniformity, block-specific styles give you granular control over individual elements. Access the **Styles** tab in the settings sidebar of each block to adjust things like:
- **Background color**: Choose a custom background color to make blocks stand out or blend seamlessly into your design.
- **Padding:** Control the space above and below block content for better visual balance.
- **Borders:** Add borders to the top and bottom of blocks, specifying styles, widths, and colors.
- **Colors, size,** and **font** of individual elements like cards, top bar section, and item fields.

## Custom code for advanced styling
If you’re limited with the default styling options, Softr’s [custom code block](/custom-code/3idxDhKqz1qPdqBuWbs61G/custom-code-block-overview/6XNrxFopUEiwbWipq81Eq1) allows for deep customization by adding HTML, CSS, or JavaScript anywhere in your application.

---
# Publish your application
Source: https://docs.softr.io/core-concepts-overview/publish-your-application
Until you publish your Softr application, it remains private and inaccessible to others. Publishing makes your app accessible on the web and allows others to interact with it.
## Previewing your Softr app
Before publishing, you can preview and test your app to see how it will appear to users. Softr Studio provides tools for testing the app in various scenarios:
- **Live preview**: Click the play icon in the top-right corner of the Studio to preview your app.
- **User role simulation**: Use the dropdown in the preview window to simulate the experience of specific user roles, ensuring personalized functionality works as intended.
- **Device testing**: Test your app's responsiveness by selecting different device screen sizes.
- **Shareable preview link**: Share a link to the preview of your application.

## Publishing your app
Publishing your app ensures it becomes accessible to users on the web. Softr assigns a default randomized subdomain (e.g., `https://.softr.io`) for initial testing. Once you’re satisfied with the app’s functionality, you can:
- **Customize your subdomain**: Personalize the randomized subdomain to reflect your brand better.
- [Connect a custom domain](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/publish-your-application/41p6U2eZs7mF8o4UyKai2g): Link a professional domain to enhance credibility and brand alignment.
After publishing, any subsequent changes to your app—such as adding new pages or modifying content—will require re-publishing to update the live version.

## Creating a Mobile App (PWA)
[Progressive web apps](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/publish-your-application/41p6U2eZs7mF8o4UyKai2g) (PWAs) transform your Softr app into a mobile-app-like experience for users, offering the convenience of installation on their devices. Key features include:
- **Customizable appearance**: Personalize the PWA’s icon, name, and splash screen to align with your brand.
- **Broad compatibility**: PWAs work seamlessly across major browsers and devices, providing a consistent user experience.
- **Easy installation**: Users can install your app directly from their browser, making it accessible from their home screen or desktop.
> **Note**
>
> This feature is available for Professional, Business, and enterprise plans.

## SEO
If you’re building a public-facing app (e.g. real estate management), SEO is your secret weapon for reaching a wider audience. Softr equips you with a suite of tools to ensure your app is easily discoverable by search engines and engaging for users. Whether you’re running a marketplace, business directory, or a landing page, you can:
- **Optimize content**: Craft compelling titles, descriptions, and URLs to enhance your pages' appearance in search results.
- **Track performance**: Integrate with Google Analytics or Search Console to monitor traffic and identify growth opportunities.
- **Enhance functionality**: Use custom code to implement advanced SEO features like structured data, which will help search engines better understand your content.
These tools enable you to turn your app into a high-performing, search-friendly destination. For a deeper dive, check out Softr’s [SEO checklist](/publishing/9qTmU2Lj8Gnpr1Ue6dEAkX/softr-seo-checklist/cfcsseCaqjKL5nCjjXWrtZ) and take your app to the next level.
---
# Softr Databases Overview
Source: https://docs.softr.io/softr-databases/softr-databases-overview
Softr Databases is a powerful, relational database tool built directly into Softr. It is designed to be the fastest and most seamless way to store, manage, and organize your application data.
Because it is native to the platform, Softr Databases offers several key advantages over external sources:
- **No API Rate Limits**: You never have to worry about hitting record fetch or update limits.
- **Superior Performance**: Faster data loading and updates with no third-party middleware.
- **All-in-One Management**: Manage your data and app logic in a single interface inside the Studio.
Think of it like a smarter spreadsheet—but perfectly optimized for building apps.

Softr gives you a few easy ways to get started with your database:
- **Start from scratch**: Set up your own tables and fields based on what your app needs.
- **Use a template**: Pick from ready-made templates (like CRM, job board, or inventory) to get started faster.
- **Import**: Bring your existing data into Softr with a simple import. Currently supporting CSV and Airtable import, with more import options coming soon.

> **Note**
>
> Softr Databases are available on all Softr plans with some record limits. For details, check out the Pricing Page.
## Step-by-Step: Create your first database
Here’s how to create your first database and understand the key pieces along the way:
1. **Create a new database and your first table**
You can add more tables by clicking on the **+** button. You have a few options to choose from:
- Start from scratch
- Generate with AI
- Import from CSV
- Import from Airtable
- Import from Google Sheets (coming soon)

2. **Add Fields**
Fields are the pieces of information you want to store about each item. These are the columns in your table.
You can add fields manually, or let the **AI Co-Builder** do it for you (e.g., _"Add a status field with options for To Do, In Progress, and Done"_ or _"Create a relationship field linked to Clients"_).
For example, if adding manually, a client might have:
- Name
- Email
- Company
- Status
Each field has a type that tells the database what kind of info it should expect. Here are a few common ones:
- **Text** – for names or notes
- **Number** – for prices or quantities
- **Date** – for deadlines or schedules
- **File/Image** – for uploading documents or pictures
- **Relationship** – to connect one table to another, like linking a project to a client


3. **Add More Tables/Fields/Records as Needed**
As your app grows, you may add more tables—such as Projects, Orders, or Support Tickets—or add more fields to collect new data, like Notes, Payment Status, and Company contacts.

That’s it—you’ve just built the foundation of your app with a well-structured database!
## Connect the Database to the Softr Application
Once you've created your database, you’re ready to build and connect to your app.
1. **Connect your data to a dynamic block**
To display your data in the app, connect a [dynamic block](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/visualize-data-with-building-blocks/41p6U2eZs7zgY8zWmFV4eH) (e.g., List, Grid, Table) to Softr Databases:
1. Go to the **Block source** **tab** and select Softr Databases
2. Pick the **Database** you want to use.

> **Note**
>
> **Important:** Each Database table can only connect to one Softr block. For example, if you want to display **Projects** in a List block, you’ll need to map it to the **Projects table** in your base. If you also want to show **Tasks**, you’ll need to add a separate block and connect it to the **Tasks table**.
> **Note**
>
> **Note**: Softr Database is compatible with the latest dynamic blocks. **Inbox** and **Kanban** don’t yet support Softr Databases. Support for these is coming soon.
2. **Map Database fields to item fields**
When you connect your table to a block, you can choose which **columns** to display and map to block fields.. This lets you control how your data appears in the app.

> **Note**
>
> Database fields work like **spreadsheet columns**, but each has a specific type (e.g., text, image, checkbox). To keep everything working smoothly, make sure to **match field types correctly** when setting up the connection.
3. **Supported field types**
All Database fields are supported in Softr Blocks. Some fields are read-only. For more detailed information about fields and their configuration, refer to the [Fields page](/softr-databases/57RHfyrVrq5xPojyELRnSu/field-types/57RHfyrVrpq8aaMPouT9Rs).
## Database structure limits
| What you're adding | Maximum allowed |
| ------------------------------------------ | --------------- |
| Databases per workspace | 1,000 |
| Tables per database | 512 |
| Fields (columns) per table | 512 |
| Options in a single- or multi-select field | 512 |
---
### FAQ
**Where is the Softr Database stored?**
All Softr Database data is currently stored in the **AWS EU Region**.
**Is Softr Databases GDPR compliant?**
Yes, Softr follows GDPR-aligned practices for data protection and privacy.
**Are Softr Databases available on the free plan?**
Yes! Softr Databases are available for everyone to try, with record limits tailored to each plan so you can build and scale with confidence. The free plan includes up to 1000 records per database (and 5000 records across databases).
**Can I add data to Softr Databases via API or automation tools?**
Yes! You can connect any tool with a REST API and push data to Softr Databases using the public API. And you connect to Zapier to power automations across your entire stack (Make and n8n integrations coming soon).
[Explore API docs →](/softr-api/tTFQ5vSAUozj5MsKixMH8C/softr-database-api/)
[Explore Softr + Zapier →](https://zapier.com/apps/softr/integrations)
---
# Field Types
Source: https://docs.softr.io/softr-databases/field-types
Softr offers a variety of field types to help you organize and manage data in your Databases effectively. Each field type is designed to store specific kinds of information, from text and numbers to files and relationships. Below is an overview of the different field types available in Softr, along with their uses and key features.

_The field types at a glance. The sections below describe each one._
## List of Field Types
### Short Text
- Purpose: Stores short text entries, such as names, titles, or IDs.
- Use Case: Ideal for fields like "Customer Name" or "Product Code."
- Features:
- Supports plain text input.
- Limited to 1024 characters.
- Can set a default value for newly created records
### Long Text
- Purpose: Stores longer text, such as descriptions or notes.
- Use Case: Perfect for fields like "Project Description" or "Customer Feedback."
- Features:
- Rich text support coming soon.
- Limited to 65,536 characters
- Can set a default value for newly created records
### File
- Purpose: Stores files, such as images, PDFs, or documents.
- Use Case: Useful for fields like "Product Image" or "Contract PDF."
- Features:
- Upload multiple files to a single record by toggling it on
- Store images, audio, docs, and other supported file types directly in Softr.
- File storage limits depend on your Softr plan.
- Maximum file size is 128MB
**Supported File Types**
- PDF
- DOCX
- DOC
- XLSX
- XLS
- PPTX
- PPT
- TXT
- CSV
- RTF
- JPG
- JPEG
- PNG
- GIF
- WEBP
- SVG
- TIFF
- TIF
- BMP
- HEIC
- MP4
- MP3
- WAV
- MOV
- AVI
- WEBM
- AAC
- M4A
- MKV
- WMV
- HTML
- CSS
- JS
- JSON
- XML
- ZIP
- RAR
- 7Z
- TAR
- GZ
- ODT
- ODS
- ODP
- PAGES
- NUMBERS
- KEY
- PSD
- AI
- INDD
- SKETCH
- FIG
- XD
- EPS
- TTF
- OTF
- WOFF
- WOFF2
- PY
- JAVA
- PHP
- CPP
- CS
- GO
- SWIFT
- SQL
- STL
- OBJ
- DWG
- DXF
- FBX
- GLTF
- SKP
- EPUB
- MOBI
- AZW
- SQLITE
- DB
- VCF
- ICS
- SRT
### Checkbox
- Purpose: Represents a true/false or yes/no value.
- Use Case: Great for fields like "Task Completed" or "Subscribed."
- Features:
- Displays as a checkbox that can be toggled on or off.
- Useful for filtering records based on status.
- Can set a default value for newly created records
### Select
- Purpose: Allows selection of one or multiple options from a predefined list.
- Use Case: Ideal for fields like "Status" (e.g., "In Progress," "Completed"), "Categories”, or even “Tags”.
- Features:
- Customizable options with color coding for visual clarity.
- Restricts input to the defined list, ensuring consistency.
- Can set a default value for newly created records

_A Select field with colored options._
### User
- Purpose: Stores the name and photo of a Softr collaborator (Workspace or App level).
- Use Case: Ideal for attaching only Softr collaborators to records
- Features:
- See the collaborators name and profile picture
- Collaborators can only see other collaborators at or below their Softr permission level
- Can set a default value for newly created records
### Number
- Purpose: Stores numerical values, such as quantities or prices.
- Use Case: Perfect for fields like "Quantity" or "Multiplier"
- Features:
- Supports integers or decimals.
- Can set precision for decimal places.
- Allows negative numbers if enabled.
- Can set a default value for newly created records.
### Currency
- Purpose: Stores monetary values with a specific currency format.
- Use Case: Ideal for fields like "Price" or "Invoice Amount."
- Features:
- Customizable currency symbol (e.g., $, €, £).
- Supports decimal precision settings.
- Aligns numbers for easy reading.
- Can set a default value for newly created records
### Percent
- Purpose: Stores percentage values.
- Use Case: Useful for fields like "Completion Rate" or "Discount."
- Features:
- Displays values with a percentage sign.
- Supports decimal precision.
- Can be used in calculations using Formulas.
- Can set a default value for newly created records.
- Can be set to display as a progress bar.
### Date
- Purpose: Stores either only date information or date and time information.
- Use Case: Great for fields like "Due Date", “Booking Time”, or “Order Placed”
- Features:
- Customizable date formats (e.g., MM/DD/YYYY).
- Optional inclusion of day of the week
- Optional time zone display
- Supports calendar picker and time picker for easy input.
- Can default to the current date and/or time
- Timezone is always displayed in your local timezone. For custom timezones, use a formula field to CONCATENATE the Date field, then use DATETIME\_FORMAT() to convert to another timezone. See [here](/softr-databases/57RHfyrVrq5xPojyELRnSu/formula-glossary/57RHfyrVrpgXaYL5w8E4uR#date-and-time-functions) for more information.
### Duration
- Purpose: Stores a length of time, rather than a point in time.
- Use Case: Perfect for fields like "Time Logged" or "Estimated Effort."
- Features:
- Choose which units the value uses — milliseconds, seconds, minutes, hours, or days
- Minutes and hours are enabled by default, and values are entered and shown as `0h 00m`
- Can set a default value for newly created records
### Email
- Purpose: Stores email addresses.
- Use Case: Perfect for fields like "Contact Email" or "User Email."
- Features:
- Validates email format to ensure accuracy.
- Limited to 320 characters
- Can be clicked to open a mail client.
- Useful for integrations with email tools.
### URL
- Purpose: Stores web addresses.
- Use Case: Great for fields like "Website" or "Reference Link."
- Features:
- Validates URL format.
- Clickable links open in a browser.
- Supports shortened display for long URLs.
- Can set a default value for newly created records.
- Limited to 2000 characters
### Phone Number
- Purpose: Stores phone numbers.
- Use Case: Ideal for fields like "Contact Number" or "Support Line."
- Features:
- Accepts various phone number formats.
- Can be clicked to initiate calls on supported devices.
- No strict format enforcement for flexibility.
- Can set a default value for newly created records.
- Limited to 25 characters
### Rating
- Purpose: Stores a rating value, typically displayed as stars.
- Use Case: Perfect for fields like "Customer Rating" or "Review Score."
- Features:
- Customizable scale (e.g., 1–10 stars)
- Visual star display
- Can set a default value for newly created records.
### Button
- Purpose: Adds a button to every record that runs a [Softr Workflow](/workflows/workflows) when clicked.
- Use Case: Perfect for row-level actions like "Send Reminder" or "Approve Request."
- Features:
- Pick an existing workflow, or create a new one straight from the field settings
- Customizable button label (defaults to "Run")
- The button stays inactive until a workflow is selected
### Formula
- Purpose: Calculates values based on other fields in the Database.
- Use Case: Great for automatically computed fields like "Total Cost" or "Customer Status" based on other fields or criteria.
- Features:
- Supports mathematical operations, text concatenation, and logical functions.
- Results are **_read-only_** and update automatically.
- For more information about using Formulas, check out [this help article](/softr-databases/57RHfyrVrq5xPojyELRnSu/formula-glossary/57RHfyrVrpgXaYL5w8E4uR).
### Rollup
> **Tip**
>
> Explore Rollups on a deeper level in [this document](/softr-databases/57RHfyrVrq5xPojyELRnSu/related-record-lookup-and-rollup-fields/57RHfyrVrnNoojNtczw14L).
- Purpose: Aggregates data from linked records in another table.
- Use Case: Useful for fields like "Total Orders" or "Related Tasks."
- Features:
- Pulls data from a linked record field.
- Supports aggregations like count, sum, or concatenation.
- Can apply formulas to rolled-up data.
### Lookup
> **Tip**
>
> Explore Lookup on a deeper level in [this document](/softr-databases/57RHfyrVrq5xPojyELRnSu/related-record-lookup-and-rollup-fields/57RHfyrVrnNoojNtczw14L).
- Purpose: Displays values from a linked record without calculation.
- Use Case: Ideal for fields like "Customer Name" from a linked table.
- Features:
- Shows data directly from a linked table.
- Read-only field that updates with changes in the source.
- Useful for displaying related information.
### Linked Record
> **Tip**
>
> Explore Linked Record fields on a deeper level in [this document](/softr-databases/57RHfyrVrq5xPojyELRnSu/related-record-lookup-and-rollup-fields/57RHfyrVrnNoojNtczw14L).
- Purpose: Creates linked records (relationships) between tables in a Database.
- Use Case: Perfect for connecting "Orders" to "Customers" or "Tasks" to "Projects."
- Features:
- Links to one or more records in another table.
- Supports one-way or reciprocal relationships.
- Enables rollups and lookups for related data.
### Created At
- Purpose: Automatically records the date and time a record is created.
- Use Case: Useful for tracking "Record Creation Date."
- Features:
- Set automatically and cannot be edited.
- Useful for sorting or filtering records.
### Last Modified At
- Purpose: Automatically records the date and time a record is last edited.
- Use Case: Great for tracking "Last Updated."
- Features:
- Updates automatically when any field in the record changes.
- Can monitor specific fields if configured.
### Created By
- Purpose: Records the Softr collaborator who created a record.
- Use Case: Ideal for fields like "Record Owner."
- Features:
- Automatically captures the user’s name or email (based on Softr account).
- **_Read-only_** field.
- Useful for collaborative Databases.
### Last Modified By
- Purpose: Records the Softr collaborator who last edited a record.
- Use Case: Useful for tracking "Last Edited By."
- Features:
- Updates automatically when a record is modified.
- **_Read-only_** field.
- Helps in collaborative databases or when performing record auditing.
### Autonumber
- Purpose: Generates a unique, sequential number for each record.
- Use Case: Perfect for fields like "Record ID" or "Ticket Number."
- Features:
- Automatically increments for each new record.
- **_Read-only_** and cannot be edited.
### Record ID
- Purpose: Displays the Softr Record ID for each record.
- Use Case: Provides a unique identifier for your records to more easily distinguish between similar records, allow you to filter and sort more easily in your Softr apps.
- Features:
- Highly unique identifier not shared by any other record in your database
- Can be used to filter, sort, and organize list and item details blocks in your apps.
## Tips for Choosing Field Types
- Match the Data: Select a field type that aligns with the data you’re storing (e.g., use Currency for money, not Number).
- Plan for Scalability: Use Linked Records for relationships to keep your Database organized as it grows.
- Leverage Automation: Fields like Formula, Rollup, and Lookup can automate calculations and actions, saving time.
- Test Display: Ensure the field type displays well in your Softr apps or views for end users.
## Additional Resources
- [Softr Academy](https://academy.softr.io/): Visit the Softr Academy to take full courses on building Softr apps.
- [Community Forums](https://community.softr.io/): Join the Softr community to ask questions and share tips.
- Support: Contact Softr support at if you get stuck with your Database setup.
---
# Formula Glossary
Source: https://docs.softr.io/softr-databases/formula-glossary
Formula fields in Softr allow you to perform calculations, manipulate text, work with dates, and create conditional logic to enhance your Database's functionality. Each function is listed with its syntax and an example to demonstrate its use.
## **Introduction to Formula Fields**
Formula fields in Softr are a powerful field type that enable you to compute values based on other fields in your Database. You can add a formula field to a table like any other field type, then write a formula to generate outputs such as numbers, dates, or text strings. These fields automatically update when referenced data changes, making them ideal for dynamic calculations and data manipulation.
### To create a formula field:
1. Add a new field to your table in Softr.
2. Select "Formula" as the field type.
3. Enter the formula in the formula editor, referencing other fields and using the functions below.
4. Configure the output format (e.g., number, date, or string) under the Formatting tab.
### Formula Syntax
- When referencing other fields inside a formula, always put them in curly brackets, like so: `{Contact Name}` or `{Status}`
- When you use a function, the function only applies to what is inside the parentheses `()`. If you need to place functions inside other functions, you can use multiple parentheses, like so:
```plain
SUM({Price}, ({Price}*{Tax Rate}))
```
- Static, text based values always need to be inside quotation marks `“` like so:
```plain
IF({Rating}<=3, "At Risk", "Nominal")
```
- Arrays (lists of items) are always displayed inside square brackets `[]`
## **Formula Functions and Operators**
### **Text Functions**
**`CONCATENATE(text1, text2, ...)`**
Combines multiple text strings into a single string.
**Example:**
```plain
CONCATENATE({First Name}, " ", {Last Name})
```
If First Name is "Jane" and Last Name is "Doe", the result is "Jane Doe".
Alternative, you can also use the ampersand symbol `&` to combine text together, like so:
```plain
{First Name} & {Last Name}
```
---
**`LEFT(string, howMany)`**
Extracts a specified number of characters from the start of a string.
**Example:**
```plain
LEFT({Project Name}, 3)
```
If Project Name is "Website Redesign", the result is "Web".
---
**`RIGHT(string, howMany)`**
Extracts a specified number of characters from the end of a string.
**Example:**
```plain
RIGHT({Product Code}, 4)
```
If Product Code is "ITEM-1234", the result is "1234".
---
**`LEN(string)`**
Returns the length of a string in characters, including symbols and spaces.
**Example:**
```plain
LEN({Description})
```
If Description is "Softr is awesome", the result is 16.
---
**`FIND(search_text, within_text, [start_position])`**
Locates the position of a substring within a string. Returns 0 if not found.
**Example:**
```plain
FIND("Softr", {App Name})
```
If App Name is "Build with Softr", the result is 12.
---
**`SEARCH(search_text, within_text, [start_position])`**
Similar to FIND, but case-insensitive. Returns 0 if not found.
**Example:**
```plain
SEARCH("softr", {App Name})
```
If App Name is "Build with SOFTR", the result is 12.
---
**`REPLACE(old_string, start_num, num_chars, new_string)`**
Replaces part of a text string with a different text string. Replacement starts at `start_num` (1-based) and replaces `num_chars` characters.
**Example:**
```plain
REPLACE({Product Code}, 6, 4, "5678")
```
If Product Code is "ITEM-1234-XYZ", the result is "ITEM-5678-XYZ".
---
**`SUBSTITUTE(text, old_text, new_text, [instance_num])`**
Replaces occurrences of a specified substring with new text.
**Example:**
```plain
SUBSTITUTE({Title}, "Old", "New")
```
If Title is "Old Project", the result is "New Project".
---
**`TRIM(text)`**
Removes leading and trailing spaces from a string.
**Example:**
```plain
TRIM({User Input})
```
If User Input is " Hello ", the result is "Hello".
---
**`LOWER(text)`**
Converts a string to lowercase.
**Example:**
```plain
LOWER({Email})
```
If Email is "", the result is "".
---
**`UPPER(text)`**
Converts a string to uppercase.
**Example:**
```plain
UPPER({Status})
```
If Status is originally "pending", the result is "PENDING".
---
`CAPITALIZE(string)`
Converts the first character of a string to uppercase and the remaining characters to lowercase.
Example:
```plain
CAPITALIZE({Status})
```
If Status is "in progress", the result is "In progress".
---
`PROPER(string)`
Capitalizes the first letter of each word in a text string and converts all other letters to lowercase.
Example:
```plain
PROPER({Full Name})
```
If Full Name is "jane doe", the result is "Jane Doe".
---
`DOMAIN(url)`
Extracts the domain name from a URL.
Example:
```plain
DOMAIN({Website})
```
If Website is "", the result is "example.com".
---
`MID(string, start_position, length)`
Extracts a substring from a string, starting at the specified position and continuing for the specified length.
Example:
```plain
MID({Product Code}, 6, 4)
```
If Product Code is "ITEM-1234-XYZ", the result is "1234".
---
`REPT(text, number_times)`
Repeats a text string a specified number of times.
Example:
```plain
REPT("*", 5)
```
The result is "\*\*\*\*\*".
---
`T(value)`
Returns the text value of the input, or an empty string if the input is not text.
Example:
```plain
T({Price})
```
If Price is 100, the result is "100". If Price is a date, the result is "".
---
`STRINGIFY(value)`
Converts any value into a string representation.
Example:
```plain
STRINGIFY({Price})
```
If Price is 100, the result is "100".
---
### **Logical Functions**
`=`, `!=`, `>`, `<`, `>=`, `<=`
Comparison operators that return TRUE or FALSE.
Example:
```plain
{Total} >= 1000
```
If Total is 1500, the result is TRUE.
---
**`IF(logical_test, value_if_true, [value_if_false])`**
Returns one value if a condition is true, another if false. If `value_if_false` is omitted and the condition is false, the result is empty.
**Example:**
```plain
IF({Total} > 1000, "Large Order", "Small Order")
```
If Total is 1500, the result is "Large Order".
---
**`AND(logical1, logical2, ...)`**
Returns TRUE if all arguments are true, FALSE otherwise.
**Example:**
```plain
AND({In Stock} = 1, {Price} > 50)
```
If In Stock is checked and Price is 75, the result is TRUE.
---
**`OR(logical1, logical2, ...)`**
Returns TRUE if any argument is true, FALSE otherwise.
**Example:**
```plain
OR({Status} = "Open", {Status} = "In Progress")
```
If Status is "Open", the result is TRUE.
---
**`NOT(logical)`**
Reverses the logical value of its argument.
**Example:**
```plain
NOT({Completed})
```
If Completed is checked (TRUE), the result is FALSE.
---
**`XOR(logical1, logical2, ...)`**
Returns TRUE if an odd number of arguments are true, FALSE otherwise.
**Example:**
```plain
XOR({Option A}, {Option B})
```
If Option A is TRUE and Option B is FALSE, the result is TRUE. If both are TRUE, the result is FALSE.
---
**`SWITCH(expression, value1, result1, [value2, result2, ...], default)`**
Evaluates an expression and returns a result based on matching values.
**Example:**
```plain
SWITCH({Priority}, 1, "High", 2, "Medium", 3, "Low", "Unknown")
```
If Priority is 2, the result is "Medium".
---
### **Numeric Functions**
`+`, `-`, `*`, `/`
Performs addition, subtraction, multiplication, or division on numbers.
Example:
```plain
{Price} * 1.1
```
If Price is 100, the result is 110 (adds 10%).
---
`^`
Raises a number to a power (alternative to POWER).
Example:
```plain
{Base Value}^2
```
If Base Value is 5, the result is 25 (5²).
---
**`ROUND(number, num_digits)`**
Rounds a number to a specified number of decimal places.
**Example:**
```plain
ROUND({Total Cost}, 2)
```
If Total Cost is 123.456, the result is 123.46.
---
**`CEILING(number, [significance])`**
Rounds a number up to the nearest integer, or to the nearest multiple of significance if specified.
**Example:**
```plain
CEILING({Quantity})
```
If Quantity is 5.2, the result is 6.
```plain
CEILING({Price}, 10)
```
If Price is 23, the result is 30.
---
**`FLOOR(number, [significance])`**
Rounds a number down to the nearest integer, or to the nearest multiple of significance if specified.
**Example:**
```plain
FLOOR({Score})
```
If Score is 7.8, the result is 7.
```plain
FLOOR({Price}, 10)
```
If Price is 27, the result is 20.
---
**`MROUND(number, multiple)`**
Rounds a number to the nearest multiple of the given number. It rounds up or down, whichever multiple is closer.
**Example:**
```plain
MROUND({Revenue}, 1000)
```
If Revenue is 93291.13, the result is 93000.
```plain
MROUND({Price}, 0.05)
```
If Price is 2.34, the result is 2.35.
---
**`ABS(number)`**
Returns the absolute value of a number.
**Example:**
```plain
ABS({Balance})
```
If Balance is -50, the result is 50.
---
**`SUM(number1, number2, ...)`**
Adds a list of numbers.
**Example:**
```plain
SUM({Price1}, {Price2})
```
If Price1 is 100 and Price2 is 200, the result is 300.
---
**`AVERAGE(number1, number2, ...)`**
Calculates the average of a list of numbers.
**Example:**
```plain
AVERAGE({Score1}, {Score2}, {Score3})
```
If Score1 is 80, Score2 is 90, and Score3 is 100, the result is 90.
---
**`MIN(number1, number2, ...)`**
Returns the smallest number in a list.
**Example:**
```plain
MIN({Bid1}, {Bid2})
```
If Bid1 is 500 and Bid2 is 450, the result is 450.
---
**`MAX(number1, number2, ...)`**
Returns the largest number in a list.
**Example:**
```plain
MAX({Revenue Q1}, {Revenue Q2})
```
If Revenue Q1 is 1000 and Revenue Q2 is 1200, the result is 1200.
---
`COUNT(array)`
Counts the number of non-null items in an array.
Example:
```plain
COUNT({Tasks Lookup})
```
If Tasks Lookup contains \["Task1", "", "Task2", "Task3"], the result is 3.
---
`MOD(number, divisor)`
Returns the remainder after dividing the number by the divisor.
Example:
```plain
MOD({Total Items}, 3)
```
If Total Items is 10, the result is 1 (10 ÷ 3 leaves a remainder of 1).
---
`SQRT(number)`
Returns the square root of a non-negative number.
Example:
```plain
SQRT({Area})
```
If Area is 16, the result is 4.
---
`RANDBETWEEN(low, high)`
Returns a random integer between the specified low and high values (inclusive).
Example:
```plain
RANDBETWEEN(1, 100)
```
The result is a random number between 1 and 100, such as 42.
---
`RAND()`
Returns a random number between 0 (inclusive) and 1 (exclusive).
Example:
```plain
RAND()
```
The result is a random decimal value such as 0.4517.
---
`NUMBER(value)`
Converts a value to type number. Returns 0 if conversion fails. Useful to ensure the result of a formula is treated as a number.
Example:
```plain
NUMBER({Quantity Text})
```
If Quantity Text is "42", the result is 42. If it is "abc", the result is 0.
### **Date and Time Functions**
For a full list of Date and Time formatting options, please see this article.
**`DATETIME_FORMAT(date, format)`**
Formats a date/time value as a text string.
**Example:**
```plain
DATETIME_FORMAT({Due Date}, "MM/DD/YYYY")
```
If Due Date is 2025-06-15, the result is "06/15/2025".
---
**`DATETIME_PARSE(string, format)`**
Converts a text string to a date/time value.
**Example:**
```plain
DATETIME_PARSE({Date Text}, "MM/DD/YYYY")
```
If Date Text is "12/31/2025", the result is a date value of 2025-12-31.
---
**`SET_TIMEZONE(date, timezone)`**
Sets a specific timezone for a date field.
**Example:**
```plain
SET_TIMEZONE({Event Date}, "America/New_York")
```
If Event Date is 2025-05-29 14:00 UTC, the result is 2025-05-29 10:00 EDT.
---
**`NOW()`**
Returns the current date and time.
**Example:**
```plain
NOW()
```
If the current time is May 29, 2025, 16:42 EDT, the result is 2025-05-29 16:42.
---
**`TODAY()`**
Returns the current date without time.
**Example:**
```plain
TODAY()
```
If today is May 29, 2025, the result is 2025-05-29.
---
**`DATEADD(date, number, unit)`**
Adds a specified number of units (e.g., days, months) to a date.
**Example:**
```plain
DATEADD({Start Date}, 7, "days")
```
If Start Date is 2025-06-01, the result is 2025-06-08.
---
**`DATETIME_DIFF(date1, date2, [unit])`**
Calculates the difference between two dates in the specified unit. Supported units: `seconds`, `minutes`, `hours`, `days`, `months`, `years` (case-insensitive). If `unit` is omitted, defaults to `seconds`.
**Example:**
```plain
DATETIME_DIFF({Due Date}, {Start Date}, "days")
```
If Due Date is 2025-06-10 and Start Date is 2025-06-01, the result is 9.
---
`CREATED_TIME()`
Returns the date and time when the record was created.
Example:
```plain
DATETIME_FORMAT(CREATED_TIME(), "MM/DD/YYYY")
```
If the record was created on May 29, 2025, the result is "05/29/2025".
---
`IS_SAME(date1, date2)`
Returns TRUE if two dates are identical, FALSE otherwise.
Example:
```plain
IS_SAME({Start Date}, {End Date})
```
If Start Date and End Date are both 2025-06-01, the result is TRUE.
---
`IS_AFTER(date1, date2)`
Returns TRUE if date1 is after date2, FALSE otherwise.
Example:
```plain
IS_AFTER({Due Date}, TODAY())
```
If Due Date is 2025-06-10 and today is May 29, 2025, the result is TRUE.
---
`IS_BEFORE(date1, date2)`
Returns TRUE if date1 is before date2, FALSE otherwise.
Example:
```plain
IS_BEFORE({Start Date}, TODAY())
```
If Start Date is 2025-05-01 and today is May 29, 2025, the result is TRUE.
---
`LAST_MODIFIED_TIME()`
Returns the most recent modification time for the record.
Example:
```plain
DATETIME_FORMAT(LAST_MODIFIED_TIME(), "MM/DD/YYYY")
```
If the record was last modified on May 28, 2025, the result is "05/28/2025".
---
`WORKDAY(start_date, num_days, [...holidays])`
Returns a date that is a specified number of working days from the start date, excluding weekends. You can optionally pass one or more holiday dates to also be excluded.
Example:
```plain
WORKDAY({Start Date}, 5)
```
If Start Date is 2025-06-02 (Monday), the result is 2025-06-09 (Monday, 5 workdays later).
```plain
WORKDAY({Start Date}, 5, "2025-06-04", "2025-06-05")
```
If Start Date is 2025-06-02 and 2025-06-04 and 2025-06-05 are holidays, the result is 2025-06-11.
---
`WORKDAY_DIFF(start_date, end_date, [...holidays])`
Returns the number of working days between two dates, excluding weekends. You can optionally pass one or more holiday dates to also be excluded.
Example:
```plain
WORKDAY_DIFF({Start Date}, {End Date})
```
If Start Date is 2025-06-02 and End Date is 2025-06-09, the result is 5 workdays.
```plain
WORKDAY_DIFF({Start Date}, {End Date}, "2025-06-04")
```
If Start Date is 2025-06-02 and End Date is 2025-06-09 and 2025-06-04 is a holiday, the result is 4 workdays.
---
`WEEKDAY(date, [startDayOfWeek])`
Returns the day of the week as a number. By default, the week starts on Sunday (1 = Sunday, 2 = Monday, ..., 7 = Saturday). Pass "monday" as the second argument to start the week on Monday instead (1 = Monday, 2 = Tuesday, ..., 7 = Sunday). Any other second argument is ignored and the default Sunday start is used. The result is 0 when the date is empty.
Example:
```plain
WEEKDAY({Due Date})
```
If Due Date is 2025-06-02 (a Monday), the result is 2.
```plain
WEEKDAY({Due Date}, "monday")
```
If Due Date is 2025-06-02 (a Monday), the result is 1.
---
`WEEKNUM(date, [startDayOfWeek])`
Returns the week number of the year for a given date. By default, the week starts on Sunday. Pass "monday" as the second argument to start the week on Monday instead.
Example:
```plain
WEEKNUM({Due Date})
```
If Due Date is 2025-06-02, the result is 23.
---
`DATESTR(date)`
Converts a date to a string in "YYYY-MM-DD" format.
Example:
```plain
DATESTR({Start Date})
```
If Start Date is June 1, 2025, the result is "2025-06-01".
---
`DATE(value)`
Converts a value to a date type.
Example:
```plain
DATE("2025-06-15")
```
The result is a date value of 2025-06-15.
---
`DATETIME(value)`
Converts a value to a datetime type.
Example:
```plain
DATETIME("2025-06-15 14:30:00")
```
The result is a datetime value of 2025-06-15 14:30:00.
---
`EDATE(date, [months])`
Returns the date that is the specified number of months before or after the start date, keeping the same day. If the day doesn't exist in the target month, it rolls to the last day of the target month. If months is omitted, defaults to 0.
Example:
```plain
EDATE({Start Date}, 3)
```
If Start Date is 2025-01-31, the result is 2025-04-30 (April has no 31st, so it rolls to the last day).
---
`EOMONTH(date, [months])`
Returns the last day of the month that is the specified number of months before or after the start date. If months is omitted, defaults to 0 (returns last day of the current month).
Example:
```plain
EOMONTH({Start Date}, 1)
```
If Start Date is 2025-06-15, the result is 2025-07-31 (last day of the following month).
---
`DAY(date)`
Returns the day of the month from a date.
Example:
```plain
DAY({Due Date})
```
If Due Date is 2025-06-15, the result is 15.
---
`MONTH(date)`
Returns the month from a date (1–12).
Example:
```plain
MONTH({Due Date})
```
If Due Date is 2025-06-15, the result is 6.
---
`YEAR(date)`
Returns the year from a date.
Example:
```plain
YEAR({Due Date})
```
If Due Date is 2025-06-15, the result is 2025.
---
`HOUR(date)`
Returns the hour from a datetime value (0–23).
Example:
```plain
HOUR({Created Time})
```
If Created Time is 2025-06-15 14:30:00, the result is 14.
---
`MINUTE(date)`
Returns the minute from a datetime value (0–59).
Example:
```plain
MINUTE({Created Time})
```
If Created Time is 2025-06-15 14:30:00, the result is 30.
---
`SECOND(date)`
Returns the second from a datetime value (0–59).
Example:
```plain
SECOND({Created Time})
```
If Created Time is 2025-06-15 14:30:45, the result is 45.
---
`DAYS_IN_MONTH([date])`
Returns the number of days in the month of the given date. If no date is provided, uses the current date.
Example:
```plain
DAYS_IN_MONTH({Due Date})
```
If Due Date is 2025-02-15, the result is 28.
### Array Functions
`ARRAYCOMPACT(values)`
Removes empty or null values from a list and returns the result as a comma-separated string.
Example:
```plain
ARRAYCOMPACT({Tasks Lookup})
```
If Tasks Lookup contains \["Task1", "", "Task2"], the result is "Task1, Task2".
---
`ARRAYJOIN(values, [delimiter])`
Joins array elements into a single string, separated by an optional delimiter.
Example:
```plain
ARRAYJOIN({Tags Lookup}, ", ")
```
If Tags Lookup contains \["Red", "Blue"], the result is "Red, Blue".
---
`ARRAYUNIQUE(values)`
Removes duplicate values from a list and returns the result as a comma-separated string.
Example:
```plain
ARRAYUNIQUE({Categories Lookup})
```
If Categories Lookup contains \["A", "B", "A"], the result is "A, B".
---
`ARRAYSLICE(array, start, [end])`
Extracts a portion of an array from the start index to the optional end index (exclusive). Indexes are 1-based.
Example:
```plain
ARRAYSLICE({Tags Lookup}, 2, 4)
```
If Tags Lookup contains \["A", "B", "C", "D"], the result is "B, C".
---
### Regular Expression Functions
`REGEX_MATCH(string, pattern)`
Returns TRUE if the string matches the regular expression pattern.
Example:
```plain
REGEX_MATCH({Email}, "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$")
```
If Email is "", the result is TRUE.
---
`REGEX_EXTRACT(string, pattern)`
Extracts the first substring that matches the regular expression pattern.
Example:
```plain
REGEX_EXTRACT({Code}, "[0-9]+")
```
If Code is "ITEM-1234-XYZ", the result is "1234".
---
`REGEX_REPLACE(string, pattern, replacement)`
Replaces all matches of the regular expression pattern with the replacement string.
Example:
```plain
REGEX_REPLACE({Phone}, "\D", "")
```
If Phone is "(123) 456-7890", the result is "1234567890".
### **Other Functions**
**`RECORD_ID()`**
Returns the unique identifier for a record.
**Example:**
```plain
RECORD_ID()
```
If the record's ID is "rec1234567890", the result is "rec1234567890".
Alternatively, if you just need the Record ID, you can also use a Record ID field type.
---
**`ISERROR(value)`**
Checks if a value or expression results in an error, returning TRUE or FALSE.
**Example:**
```plain
ISERROR({Price} / 0)
```
If Price divided by 0 causes an error, the result is TRUE.
---
**`BLANK()`**
Returns an empty string.
**Example:**
```plain
IF({Name} = "", BLANK(), {Name})
```
If Name is empty, the result is an empty string; otherwise, it returns the value of Name.
---
**`ERROR()`**
Returns an error value.
**Example:**
```plain
IF({Quantity} < 0, ERROR(), {Quantity} * {Price})
```
If Quantity is -1, the result is an error.
---
**`IFERROR(expression, fallback)`**
Returns the value of the expression if it is not an error; otherwise, returns the fallback value.
**Example:**
```plain
IFERROR({Total} / {Count}, 0)
```
If Count is 0 and the division causes an error, the result is 0.
---
**`TRUE()`**
Returns the number 1 (true).
**Example:**
```plain
IF(TRUE(), "Always", "Never")
```
The result is "Always".
---
**`FALSE()`**
Returns the number 0 (false).
**Example:**
```plain
IF(FALSE(), "Always", "Never")
```
The result is "Never".
---
## **Tips for Writing Formulas**
- **Plan Ahead**: Before writing a formula, outline your goal in plain language (e.g., "Calculate the days remaining until a deadline").
- **Check Syntax**: Softr's formula editor highlights errors. Ensure field names are correct and enclosed in curly braces \{}.
- **Use Nesting**: Combine functions for complex logic, such as nested IF statements:
```plain
IF({Score} > 90, "A", IF({Score} > 80, "B", "C"))
```
- **Format Outputs**: Use the Formatting tab to set the desired output format (e.g., decimal places for numbers, date styles for dates).
- **Test Thoroughly**: Preview your formula results in Softr to confirm they behave as expected.
## **Common Use Cases**
- **Dynamic Text**: Combine names or create custom labels:Result: "New York - USA"
```plain
CONCATENATE({City}, " - ", {Country})
```
- **Conditional Logic**: Categorize records based on criteria:Result: "High" or "Low"
```plain
IF({Revenue} > 10000, "High", "Low")
```
- **Date Calculations**: Track project timelines:Result: Number of days until the due date
```plain
DATETIME_DIFF({Due Date}, TODAY(), "days")
```
- **Numeric Calculations**: Compute totals or percentages:Result: 10% of Price, rounded to two decimals
```plain
ROUND({Price} * 0.1, 2)
```
## **Limitations**
- Formula fields are read-only and cannot be manually edited.
- Complex formulas may impact performance in large Databases.
- Some functions (e.g., FIND vs. SEARCH) are case-sensitive; choose the appropriate function for your needs.
- Ensure referenced fields exist and contain valid data to avoid errors.
## Additional Resources
- [Softr Academy](https://academy.softr.io/): Visit the Softr Academy to take full courses on building Softr apps.
- [Community Forums](https://community.softr.io/): Join the Softr community to ask questions and share tips.
- Support: Contact Softr support at if you get stuck with your Database setup.
---
# Related Record, Lookup, and Rollup Fields
Source: https://docs.softr.io/softr-databases/related-record-lookup-and-rollup-fields
You can use related record, lookup, and rollup fields in Softr to manage and display data across tables in your Database. These field types allow you to connect data, pull information from related records, and perform calculations or aggregations, enhancing the functionality of your Softr Databases and Softr Apps.

_A related record field links the tables. Lookup and rollup fields then read from the linked records._
## Related Records
A related record field (also known as a relationship field) allows you to connect records between two tables in a Softr Database. By establishing linked records, you can reference data from one table in another, creating dynamic connections between datasets.
### How to Set Up a Related Record Field
1. Navigate to Your Database: Open your Softr Database and select the table where you want to add a related record field.
2. Add a New Field: Click **Add field** at the end of the table header.
3. Choose Related Record Field Type: Select “Related record” from the field type dropdown.
4. Link to Another Table: Choose the **Source table** to link to. For example, if you have a "Tasks" table and a "Users" table, you can link each task to a specific employee in your Users table.
5. Configure the related record field:\
- Softr will automatically create a corresponding related record field in the linked table.
- Decide if the relationship is one-to-one, one-to-many, or many-to-many by toggling **Allow linking to multiple records** on the related record fields in both tables.
6. Save: Name the field(s) and click Save.\

_Creating a related record field that links each task to a user._
### Example Use Case
- Database Setup: You have a "Tasks" table and a "Users" table.
- Relationship: Create a related record field in the "Tasks" table to assign each task to a person from the "Users" table.
- Result: Each task record can now display the assigned employee’s name, and the "Users" table can show all tasks assigned to each employee.
### Tips
- Use related record fields to avoid duplicating data across tables.
- Related record fields are bidirectional, so changes in one table will reflect in the linked table.
## Lookup Fields
A lookup field pulls data from a related table via Related record field. It allows you to display specific fields from related records without manually copying the data.
### How to Set Up a Lookup Field
1. Ensure a Related record field Exists: You must have a related record field connecting two tables (e.g., "Projects" linked to "Clients").
2. Add a Lookup Field: In the table with the Related record field, click **Add field** and select **Lookup** as the field type.
3. Select the **Lookup source**: Choose the Related record field that connects to the other table.
4. Choose the Field to Display: Under **Field to look up**, select the field from the linked table you want to show (e.g., "Phone" or "Email").
5. Save: Name the lookup field and save.

_A lookup field that shows the client phone number on each project._
### Example Use Case
- Database Setup: The "Projects" table has a Related record field linking to the "Clients" table.
- Lookup Field: Create a lookup field in the "Projects" table to display the "Client Phone Number" from the linked client record.
- Result: Each project record now shows the client’s phone number alongside other project details.
### Tips
- Lookup fields are _**read-only**_ and update automatically when the source data changes.
- Use lookup fields to display supplementary information without cluttering your table with manual entries.
## Rollup Fields
A rollup field aggregates or transforms data from a related table using a formula. It builds on a Related record field and allows you to summarize, count, or manipulate data from linked records.
### How to Set Up a Rollup Field
1. Ensure a Related record field exists: You need a Related record field connecting two tables.
2. Add a Rollup Field: In the table with the related record field, click **Add field** and select **Rollup** as the field type.
3. Select the related record field under **Related records to roll up from**.
4. Choose the Field to Roll Up: Select the field from the linked table you want to aggregate, under **field to roll up** (e.g., "Task Status" or "Invoice Amount").
5. Define the Formula: Pick the **Aggregation formula**. Options include:\
- **MIN:** Finds and displays the minimum numeric value of a list of related records for a specific field.
- **MAX:** Finds and displays the maximum numeric value of a list of related records for a specific field.
- **SUM:** Adds all numeric values of a specific field for a list of related records
- **AVERAGE:** Averages all numeric values of a specific field for a list of related records
- **COUNT:** Counts the number of non-empty numeric values for a list of related records
- **COUNTA:** Counts the number of non-empty text or numeric values for a list of related records
- **COUNTALL:** Counts the number of all values (even empty ones) for a list of related records
- **ARRAYJOIN:** Concatenates all elements into a single string separated by semicolons (e.g. \[1, 2] → "1; 2")
- **ARRAYUNIQUE:** Removes duplicate items, preserving the first occurrence of each.
- **ARRAYCOMPACT:** Strips out blank/empty/NULL elements.
6. Save: Name the rollup field and save.\
> **Tip**
>
> If you only need to count the number of related records, use the COUNTALL function.

_A rollup field that sums the invoice totals of each project._
### Example Use Case
- Database Setup: The "Projects" table is linked to the "Invoices" table via a related record field.
- Rollup Field: Create a rollup field in the "Projects" table to calculate the total "Invoice Amount" for all invoices linked to each project.
- Formula: Use **SUM** to add up the invoice amounts.
- Result: Each project record displays the total invoiced amount for a given project.
### Tips
- Rollup fields are dynamic and update when related records change.
- Use rollup fields for calculations like totaling values, counting records, or filtering arrays of data
## Key Differences and When to Use Each
| | | |
| -------------- | --------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| **Field Type** | **Purpose** | **When to Use** |
| Related Record | Connects records between two tables. | To link related data, such as assigning tasks to employees or projects to clients. |
| Lookup | Displays data from a related table’s field. | To show additional details from related records, like a client’s contact info in a project table. |
| Rollup | Aggregates or transforms data from related records. | To summarize or calculate data, such as totaling invoices or counting completed tasks. |
## Best Practices
- Plan Your Database Structure: Before adding related record fields, map out how your tables should connect to avoid redundant links. Think about the “nouns” of your application and avoid using adjectives in your table names - save those for Category, Type, or Status fields.
- Use Descriptive Field Names: Clearly name related record, lookup, and rollup fields to make their purpose obvious (e.g., "Related Client Name" or "Total Invoice Rollup").
- Test Formulas in Rollups: Double-check rollup formulas to ensure they produce the expected results, especially for complex aggregations.
- Limit Lookup and Rollup Fields: Too many can slow down your Database, so only include what’s necessary for visibility in your app.
## Troubleshooting
- Related Record Field Not Showing Records: Ensure both tables are in the same Database and that the related record field is correctly configured.
- Lookup Field Is Blank: Verify that the related record field has linked records and that the target field in the linked table contains data.
- Rollup Field Shows Errors: Check the formula being used and ensure the source field in the linked table has compatible data (e.g., numbers for SUM, MIN, etc.).
## Additional Resources
- [Softr Academy](https://academy.softr.io/): Visit the Softr Academy to take full courses on building Softr apps.
- [Community Forums](https://community.softr.io/): Join the Softr community to ask questions and share tips.
- Support: Contact Softr support at if you get stuck with your Database setup.
---
# Database AI Agents
Source: https://docs.softr.io/softr-databases/ai-agents
## Overview
Database AI Agents are AI helpers that live inside your Softr Databases fields. (This is distinct from any other AI feature in Softr; throughout this page, "Database AI Agents" always refers to the AI helpers that run on fields in Softr Databases.) They can auto-fill and tag fields, summarize insights, pull details from PDFs, enrich records with live web data, and more. You decide when they run, with filters and conditions to make sure they only trigger on the records you want.
## How to Add a Database AI Agent to a Field
1. **Add an AI field**
Open your table in Softr Databases. Add a new **AI field**, or edit an existing text field and toggle on **Let AI auto-fill this field** in the AI tab.

_Open the AI tab of the field editor and turn on Let AI auto-fill this field._
2. **Pick a model and write your prompt**
Pick the AI model. You can choose from models by leading providers like Anthropic, OpenAI, and Gemini, depending on the balance of speed, accuracy, and cost you need. Then write your own prompt, like _‘Summarize the resume into key skills’_, or start with a ready-made template. Use **@** to reference other database fields in your prompts.

_Pick a model and write the prompt. Type @ to insert another field._
3. **Set when the agent runs**
Under the **Run When** section, set whether the agent is triggered manually OR runs automatically when a record is created or updated. Add **Only run if…** filters so the agent triggers only when conditions are met (e.g. run only if **Status = ‘Approved’**). This prevents unnecessary runs and saves credits.

_Choose when the agent runs, and add Only run if filters._
4. **Preview and save**
Under **Preview**, select a record to generate a preview of what the agent will populate and how many AI credits it will consume. Click **Save** when you’re ready to activate the agent.

_Run a preview on one record. The coin count shows the credits used._
## Web Search
AI Agents can search the web to enrich your data, for example, pulling the latest company info, fact-checking details, or adding context. Toggle on **Allow web search** in the AI settings, then specify in your prompt what to look up and how to format it (e.g. ‘Find the latest average delivery rates in Ontario; extract the number and cite the domain in brackets’).
## AI Settings & Conditions
You’re fully in control of **when** and **how** your AI agents run:
- **Allow manual edits:** Toggle this on to enable review on AI-generated fields.
- **Model**: Choose from dozens of models by leading providers like Anthropic, OpenAI, and Gemini, depending on the task and the balance of speed, accuracy, and cost you need.

_Each model shows a short description and its relative credit cost._
- **Run mode options:**
- **Triggered manually:** Run the agent only when you click. Useful for testing or expensive operations.
- **New record is created:** Runs automatically when a new record is added.
- **Existing record is updated:** Runs automatically when an existing record is updated.
- **Skip when value already exists:** Prevents the agent from running if the field already has data (so existing values aren’t overwritten).
- **“Only run if…” filters & conditions:** Add rules to specify exactly when the agent should run. Example: Run only if **Status = “Ready for AI”** or **Category = “Hardware.”**
## Agent Templates
Start from a ready-made agent template by clicking **Template** in the AI field settings to see a task description that you can customize to your needs.

_Start from a template, then edit the prompt._
## AI Credits & Billing
- **Included credits:** Every **Softr plan (including Free)** comes with a set number of AI credits you can use with Softr’s AI features. If you use up your monthly AI credits, AI features will pause until your credits reset with your plan, or you add more with a credit add-on. [Learn more about AI credits](/workspace-and-billing/jZP6yaeXMiJCuB6HhS4xKd/ai-credits/5VRMhf7Q6xvy7AJqyiQLx5).
- **Checking Database Agent AI credit usage:** When you’re setting up an AI agent, use the Preview function to check what a run will cost (but note that every run will be different due to many factors). Credit usage depends on factors like the AI model selected, action type and input size, number of records processed, web search, and output length and format.
- **Visibility:** You can see credit usage in your Plans & Billing page.
---
## FAQs
**What are Softr Database AI Agents?**
Think of AI agents as helpers that handle your most tedious data tasks, like auto-filling fields, summarizing information, pulling insights from PDFs and the web, and keeping your records accurate in real time.
**Can I use AI agents on the free plan?**
All Softr plans (including Free) include monthly AI credits, and paid plans can purchase credit add-ons as needed.
When you’re setting up an AI agent, use the preview function to check what a run will cost (but note that every run will be different due to many factors). Credit usage depends on factors like the AI model selected, input size, number of records processed, web search, and output length.
**How do AI credits work?**
AI credits reset on a monthly basis according to your plan (see the pricing page for more details). If you run out of credits, your AI features will pause running until your monthly credits reset with your plan or you purchase add-on credits.
**Can you help me set up my agents?**
You can write your own prompts or use our sample templates to define the database tasks you want AI to handle. Use “@” to reference other database fields in your prompts.
**Can I control when and how an agent runs?**
Yes, you can choose to run AI agents manually or automatically when records are added or updated. You can also add filters and conditions (“only run when…”) so agents trigger only on the records you specify. This added level of customization gives you more control over your AI credits and costs.
**Can I choose which AI model powers my agent?**
Yes. Pick from dozens of models by leading providers like Anthropic, OpenAI, and Gemini, depending on the task and the balance of speed, accuracy, and cost you need.
**Can I test an agent before turning it on?**
Yes. Use the **Preview** section in a field’s AI settings to see the output on a sample record before saving the agent or running it on bulk records.
**What fields can I use AI agents in?**
Most text-like fields are supported. Agents cannot write to system fields (ID, Created/Updated at) or calculated fields (Formula/Rollup).
**How do I get AI to extract information from files or PDFs?**
Place the file URL or attachment in a field (e.g., _File_ or _URL_). Then use the PDF/Extraction prompt templates to parse, search, or summarize the text (e.g., “summarize this contract”), referencing the field where the file is attached, e.g. @file.
**How do I run web search?**
Toggle on **Allow web search** in a field’s AI settings, then write a prompt telling the agent what to look up, the format you want the output in, and websites to reference (optional). Preview results before enabling auto-runs. For best results, be specific in your prompt and add conditions (e.g. only search when “Market data” is empty).
---
# Datetime Formatting
Source: https://docs.softr.io/softr-databases/datetime-formatting
In Softr Databases, formula fields, workflows and in a few other select places within Softr, you may need to reformat date or datetimes in specific ways. The glossary below is a guide for creating these timestamps in various formats for user-friendly and computer-friendly dates and datetimes.
# Date-Time Pattern Reference
All letters 'A' to 'Z' and 'a' to 'z' are reserved as pattern letters. The following pattern letters are defined:
## Pattern Letters
| Symbol | Meaning | Presentation | Examples |
| ------ | -------------------------- | ------------ | --------------------------------------------- |
| G | era | text | AD; Anno Domini; A |
| u | year | year | 2004; 04 |
| y | year-of-era | year | 2004; 04 |
| D | day-of-year | number | 189 |
| M/L | month-of-year | number/text | 7; 07; Jul; July; J |
| d | day-of-month | number | 10 |
| Q/q | quarter-of-year | number/text | 3; 03; Q3; 3rd quarter |
| Y | week-based-year | year | 1996; 96 |
| w | week-of-week-based-year | number | 27 |
| W | week-of-month | number | 4 |
| E | day-of-week | text | Tue; Tuesday; T |
| e/c | localized day-of-week | number/text | 2; 02; Tue; Tuesday; T |
| F | week-of-month | number | 3 |
| a | am-pm-of-day | text | PM |
| h | clock-hour-of-am-pm (1-12) | number | 12 |
| K | hour-of-am-pm (0-11) | number | 0 |
| k | clock-hour-of-am-pm (1-24) | number | 0 |
| H | hour-of-day (0-23) | number | 0 |
| m | minute-of-hour | number | 30 |
| s | second-of-minute | number | 55 |
| S | fraction-of-second | fraction | 978 |
| A | milli-of-day | number | 1234 |
| n | nano-of-second | number | 987654321 |
| N | nano-of-day | number | 1234000000 |
| V | time-zone ID | zone-id | America/Los\_Angeles; Z; -08:30 |
| z | time-zone name | zone-name | Pacific Standard Time; PST |
| O | localized zone-offset | offset-O | GMT+8; GMT+08:00; UTC-08:00 |
| X | zone-offset 'Z' for zero | offset-X | Z; -08; -0830; -08:30; -083015; -08:30:15 |
| x | zone-offset | offset-x | +0000; -08; -0830; -08:30; -083015; -08:30:15 |
| Z | zone-offset | offset-Z | +0000; -0800; -08:00 |
| p | pad next | pad modifier | 1 |
| ' | escape for text | delimiter | |
| '' | single quote | literal | ' |
| \[ | optional section start | | |
| ] | optional section end | | |
| # | reserved for future use | | |
| \{ | reserved for future use | | |
| } | reserved for future use | | |
## Pattern Letter Count
The count of pattern letters determines the format:
### Text
The text style is determined based on the number of pattern letters used:
- **Less than 4 letters**: Short form
- **Exactly 4 letters**: Full form
- **Exactly 5 letters**: Narrow form
Pattern letters 'L', 'c', and 'q' specify the stand-alone form of the text styles.
### Number
If the count of letters is one, then the value is output using the minimum number of digits and without padding. Otherwise, the count of digits is used as the width of the output field, with the value zero-padded as necessary.
**Constraints:**
- Only one letter of 'c' and 'F' can be specified
- Up to two letters of 'd', 'H', 'h', 'K', 'k', 'm', and 's' can be specified
- Up to three letters of 'D' can be specified
### Number/Text
- **3 or more letters**: Use the Text rules above
- **Otherwise**: Use the Number rules above
### Fraction
Outputs the nano-of-second field as a fraction-of-second. The nano-of-second value has nine digits, thus the count of pattern letters is from 1 to 9. If it is less than 9, then the nano-of-second value is truncated, with only the most significant digits being output.
### Year
The count of letters determines the minimum field width below which padding is used. If the count of letters is two, then a reduced two digit form is used:
- **For printing**: Outputs the rightmost two digits
- **For parsing**: Parses using the base value of 2000, resulting in a year within the range 2000 to 2099 inclusive
If the count of letters is less than four (but not two), then the sign is only output for negative years as per `SignStyle.NORMAL`. Otherwise, the sign is output if the pad width is exceeded, as per `SignStyle.EXCEEDS_PAD`.
## Special Formatting Rules
### Zone ID (V)
Outputs the time-zone ID, such as 'Europe/Paris'. If the count of letters is two, then the time-zone ID is output. Any other count of letters throws `IllegalArgumentException`.
### Zone Names (z)
Outputs the display name of the time-zone ID:
- **1-3 letters**: Short name
- **4 letters**: Full name
- **5+ letters**: Throws `IllegalArgumentException`
### Offset X and x
Formats the offset based on the number of pattern letters:
- **One letter**: Just the hour (e.g., '+01'), unless the minute is non-zero (e.g., '+0130')
- **Two letters**: Hour and minute without colon (e.g., '+0130')
- **Three letters**: Hour and minute with colon (e.g., '+01:30')
- **Four letters**: Hour, minute, and optional second without colon (e.g., '+013015')
- **Five letters**: Hour, minute, and optional second with colon (e.g., '+01:30:15')
- **6+ letters**: Throws `IllegalArgumentException`
**Note:** Pattern letter 'X' (upper case) outputs 'Z' when the offset is zero, whereas 'x' (lower case) outputs '+00', '+0000', or '+00:00'.
### Offset O
Formats the localized offset based on the number of pattern letters:
- **One letter**: Short form of localized offset text (e.g., 'GMT+8')
- **Four letters**: Full form with 2-digit hour and minute (e.g., 'GMT+08:00')
- **Other counts**: Throws `IllegalArgumentException`
### Offset Z
Formats the offset based on the number of pattern letters:
- **1-3 letters**: Hour and minute without colon (e.g., '+0130'). Outputs '+0000' when offset is zero
- **Four letters**: Full form of localized offset (equivalent to four letters of Offset-O). Outputs corresponding localized offset text if offset is zero
- **Five letters**: Hour, minute, with optional second if non-zero, with colon. Outputs 'Z' if offset is zero
- **6+ letters**: Throws `IllegalArgumentException`
### Optional Section
The optional section markers `[` and `]` work exactly like calling `DateTimeFormatterBuilder.optionalStart()` and `DateTimeFormatterBuilder.optionalEnd()`.
### Pad Modifier (p)
Modifies the pattern that immediately follows to be padded with spaces. The pad width is determined by the number of pattern letters. This is the same as calling `DateTimeFormatterBuilder.padNext(int)`.
**Example:** 'ppH' outputs the hour-of-day padded on the left with spaces to a width of 2.
## Important Notes
- Any unrecognized letter is an error
- Any non-letter character, other than `[`, `]`, `{`, `}`, `#` and the single quote will be output directly
- Despite this, it is recommended to use single quotes around all characters that you want to output directly to ensure that future changes do not break your application
---
# Database Snapshots
Source: https://docs.softr.io/softr-databases/database-snapshots
A **snapshot** is a point-in-time copy of a whole Softr database: its tables, fields, views, records, and the links between related records. Take one before any change you might want to walk back: a bulk import, a field type change, a mass delete, or the first run of a new workflow against real data.
Restoring a snapshot creates a **new** database and leaves the original exactly as it is, so recovering data is never destructive. You get the old and the new side by side and decide what to do next.
> **Note**
>
> Snapshots apply to the entire database. You cannot snapshot a single table or view.
## Taking a snapshot
1. **Open the Snapshots panel**
Open the database, click its name in the top-left corner, and choose **Snapshots**. The panel opens on the right.

_Click the database name, then choose Snapshots._
2. **Take the snapshot**
Click **+ Take a snapshot**, optionally give it a name, and confirm with **Take snapshot**.

_Naming a snapshot before taking it. The name is optional._
3. **Wait for it to become ready**
The snapshot appears in the panel straight away with a **CREATING…** badge, and the **Take a snapshot** button is disabled while it works. After a few seconds the badge changes to **READY** and the snapshot can be restored.
> **Tip**
>
> If you leave the name blank, Softr calls the snapshot **Snapshot of \**. Every snapshot already shows the date and time it was taken underneath its name, so a name that records _why_ you took it (`Before Q3 equipment import`) is far more useful later than one that repeats the timestamp.
## Managing your snapshots
The panel lists every snapshot for the database, newest first, each with its name, the date and time it was taken, and its status. Hovering a snapshot reveals its two actions.

_Each ready snapshot can be restored to a new database (1) or deleted (2)._
1. **Restore to a new database**: builds a new database from this snapshot.
2. **Delete**: removes the snapshot.
> **Warning**
>
> Deleting a snapshot is permanent and cannot be undone. Since restoring never overwrites anything, there is no benefit to clearing out snapshots you might still want. Keep the ones that mark a meaningful "before" point.
## Restoring a snapshot
Restoring does **not** roll your database back in place. It creates a separate copy, which means you can restore freely without risking the data you have now.
1. **Start the restore**
Hover the snapshot you want and click **Restore to a new database**. Softr confirms what will happen before doing anything.

_The confirmation spells it out: a new database is created and the current one is left alone._
2. **Open the restored database**
The new database appears in your **Databases** list as **Restored: \**, with the tables, fields, views and records the snapshot captured.

_The restored copy sits alongside the original, which is unchanged._
The restored database is independent from that point on. Your apps keep reading from the original database until you connect them to the restored one, so you can open both, compare them, and copy across only what you need.
## Snapshots vs. App History
The two features protect different things, and one is not a substitute for the other:
- **Snapshots** capture your **data**: the contents and structure of a database.
- [**App History**](/application-settings/app-history) captures your **app**: its pages, blocks and settings. Restoring an earlier app version does not bring back deleted records.
If you are about to make a change that touches both, take a snapshot _and_ note the app version before you start.
## Related
[**Expanded Record View**](/softr-databases/expanded-record-view)
Open a record to see and edit all of its fields in one panel.
[**Softr Databases Overview**](/softr-databases/softr-databases-overview)
How Softr Databases work, and their structure limits.
[**Field Types**](/softr-databases/field-types)
Every field type available in a Softr database.
[**App History**](/application-settings/app-history)
Restore an earlier version of your app.
[**Migrate data from Airtable**](/migration-tips/migrating-from-airtable-to-softr-databases)
Move an Airtable base into Softr Databases.
---
# Expanded Record View
Source: https://docs.softr.io/softr-databases/expanded-record-view
A table only shows as many columns as fit across your screen, so a record with a long description, a dozen linked records and a cover image is impossible to take in from the grid. Expanding a record opens it in a panel that lists every field in the current view, one under another, with each value editable in place.
## Expand a record
1. **Open the table**
Open your database and select the table you want to work in.
2. **Hover over the record**
Hover over the row. An expand icon (two diagonal arrows) appears at the right edge of the first column.
3. **Click the expand icon**
The record opens in a panel over the table.

_Hover over a row and the expand icon appears at the right edge of the first column._
Every field in the view is listed in order, each with its field-type icon, its name, and its value in an editable control.

_The expanded record, with each field stacked under the record's primary value._
Editing here works exactly as it does in the grid: change a value and it saves straight away. There is no save button. Read-only fields such as formulas, rollups and lookups appear greyed out and can't be edited from the panel, the same as in the table.
> **Note**
>
> The expanded record follows the view it was opened from. A field you have hidden through the fields control is hidden here too. Show it again in the view and it reappears in the panel.
## Controls at the top of the panel

_The controls in the expanded record's header._
1. **Previous and next record.** Step through the records of the current view without going back to the grid. The arrows follow the view's own filters and sort order, and the upward arrow is greyed out on the first record, the downward arrow on the last.
2. **Copy link to this record.** Copies a link that reopens the database with this record already expanded. Use it to point a teammate at one row from a ticket or a chat message. Whoever opens it still needs access to the database.
3. **Revision history.** Opens the history panel described below.
The record's ID is shown beside these controls, and **Escape** or the **✕** closes the panel.
## Revision history
Revision history records every change made to the record: who made it, when, which field, and what the value was before and after.

_Revision history opens alongside the record and lists each change with its previous and new value._
A banner at the top of the panel states how far back the history goes on your plan. Changes made before Softr started tracking revisions aren't shown. On older records, the panel says so at the end of the list.
## Related
[**Database Snapshots**](/softr-databases/database-snapshots)
Take a point-in-time copy of a database and restore it later.
[**Softr Databases Overview**](/softr-databases/softr-databases-overview)
Create a database, add tables, and connect it to an app.
[**Field Types**](/softr-databases/field-types)
What each field type stores and how it behaves.
[**Related Record, Lookup, and Rollup Fields**](/softr-databases/related-record-lookup-and-rollup-fields)
Link records across tables and pull values between them.
[**Formula Glossary**](/softr-databases/formula-glossary)
The functions available in formula fields.
---
# Workflows
Source: https://docs.softr.io/workflows/workflows
# **Softr Workflows Overview**
Softr Workflows let you automate tasks, logic, and AI-powered actions directly inside Softr. You can connect your apps, databases, and external tools to reduce manual work and keep everything in sync. Think of Workflows as the automation layer that powers your entire Softr stack.
Unlike external automation tools, Workflows are native to Softr, so they can respond to in-app user actions and database changes and use your app's data/permissions directly.
## **Step-by-Step: Create your first Workflow**
1. **Create a new Workflow**
From your Softr workspace, click **Workflows** in the left sidebar to open the visual builder. You can start in one of two ways:
- **From scratch:** Build your workflow manually by choosing a trigger and adding actions.
- **From a template:** Pick a ready-made automation (for example, "Send email alerts when a number reaches a certain threshold") and customize it.
- **With AI:** Click the AI Co-builder icon and describe your automation!

---

2. **Select a trigger**
Start by selecting a trigger for your workflow **to define when it runs**. The trigger picker has three lists:
- **Softr:** Triggers for [Softr Databases](/softr-databases/softr-databases-overview) and Softr Apps.
- **Built-in:** Email received, Webhook, One-time schedule, and Recurring schedule.
- **Integrations:** Triggers for 24 tools, including Airtable, Gmail, Google Sheets, Notion, HubSpot, Slack, and Stripe.

_The trigger picker._
Select a tool or a built-in trigger to see what it offers. A badge on each trigger shows how it starts. **Instant** triggers run right away. The other triggers check for new data at an interval, and the shortest interval depends on your plan.
**Softr Databases** triggers run when:
- **Record added**, **Record deleted**, or **Record updated:** A record changes in a table.
- **Record meets conditions:** A record matches conditions that you set, for example when **Status** changes to "Approved" or **Sentiment** is "negative".
- **Record enters view:** A record enters the selected view.
- **Run manually:** A workspace member runs the workflow by hand.

_The Softr Databases triggers._
**Softr Apps** triggers are in two groups:
- **Data triggers:** **User added** and **Comment added**.
- **UI triggers:** **Run custom workflow** (a user clicks a Run Custom Workflow action button), **Submit form**, **Add record**, and **Edit record**.

_The Softr Apps triggers._
**Note:** Triggers can reference your Softr app and Database directly, with no external connector.
3. **Add actions**
Actions define what happens after the trigger. You can run simple to complex workflows depending on what you need. Common actions include:
- **Update, add, delete, or find records** in Softr Databases
- **Send** emails (in Gmail, Outlook, Postmark, or connect another tool with API)
- **Send** a Slack message
- **Generate** AI summaries or responses using Softr's built-in LLM integrations or by bringing your own API key.
- **Add** an event in Google Calendar
- **Call API** to connect to any external system that supports REST API calls
- **Extract PDF** or **scrape webpage** to find relevant information
- **Logic-based actions**, including **Branches**, **Filters**, **Wait times**, and **Bulk actions**.
Each action can use **variables** from earlier steps (e.g., fields from the triggering record or form submission). Map these inputs in the action's **Settings** tab on the right panel.
Note: AI-based actions using Softr's built-in LLM integrations (for example, summarizing text or enriching data) use **AI credits**. Learn more about AI credits →

_A workflow on the canvas: a trigger, branches by a condition, and actions._
The action picker lists actions by category on the left: Most used, AI, Communication, Data, Payments, Events, Documents, Logic, and Utilities. Use the search to find an action by name.

_The action picker._
Select **Softr Databases** to see its actions, such as adding, updating, finding, and deleting records.

_The Softr Databases actions._
4. **Add settings and conditions**
For each trigger and action you add, you choose settings and conditions (in the **Settings** tab on the right panel). For example:
- **For Softr Database triggers:** choose **Account → Database → Table**, and (optionally) **field-level conditions** that must be true for the workflow to run.
- **For action steps (e.g., Gmail/Slack/API/AI):** connect the provider/account, **map inputs** from earlier steps (such as subject, body, channel, payload), and configure any action-specific options.
- **For logic steps:** define conditions in **Filters/Branches** or **Wait** times.

5. **Test and monitor your workflow**
Before going live, use the **Testing** tab in the right panel to ensure the action is working correctly.
For event-based triggers (e.g., Softr App or Database), create a **real test event** first—submit the form, click the button, or add/update a record—then open **Testing** to pull in the latest sample data.
Some action types don't support test preview yet such as flow controls like branching and filtering. However subsequent steps don't need test data from these steps to be configured. You can continue testing in subsequent actions even without generating test data from flow controls.

6. **Turn it on**
Once tested, click **Turn on** to set your workflow live. **It will** automatically run each time its trigger condition is met.
## Using the AI Co-builder
When building your workflow, you don't have to assemble everything step-by-step. Click the AI icon in the bottom right (above the chat icon) and describe what you want in plain English.
**Example Prompts:**
- _"When a new Deal is moved to 'Closed Won' in the CRM, send a Slack message and trigger a congratulatory email."_
- _"Every Monday morning, find all tasks that are overdue and email a summary to the manager."_
The AI Co-builder will instantly generate the full workflow outline (trigger, actions, and logic). You can then modify any of the steps visually before turning it on!

## **Connecting Workflows to your Softr apps**
Workflows can be triggered directly from user interactions inside your app.
To set up this trigger,
- Set up a workflow from **Softr Apps > Run custom workflow** and give it a name (e.g. Slack alert from record added). Publish the workflow when ready.
- Open your Softr app
- In the dynamic block you want to add the workflow, go to the **Actions** tab > **Add item button** and select **Run Custom Workflow**.
- Select the workflow.
- Define the **data to use in the workflow** (map form fields or record fields) and open **Preview** to trigger a test event
- Return to the workflow editor to **test your trigger**
Example: Pass `User name`, `Email`, and `Message` from the form to your Slack action so the team sees the full context.
You can also guide users through the flow by showing **progress or wait screens** while the workflow runs, then display confirmation once it completes.
To add a wait screen:
- Toggle on **Show wait screen** in the app action that triggers the workflow
- Add your custom message
Note: Wait/progress screens apply to app-triggered workflows (not Database/scheduled triggers).

## **Monitoring and managing your Workflows**
Click **Runs** in the top left of the visual builder to monitor performance and usage. The Runs list shows every execution with timestamps and step-by-step logs (inputs, outputs, and errors) for troubleshooting.
Run retention limits by plan:
- **Free plan:** 7 days
- **Starter:** 30 days
- **Professional:** 60 days
- **Business:** 90 days
You can pause, duplicate, or delete workflows anytime from the main **Workflows** list.
## Pricing and credits
Workflows are available on all Softr plans. Usage is based on **action executions** — how many workflow actions run while your workflows are active. Each action that runs counts toward your monthly **Workflow action limit**, depending on your plan.
### **Workflow usage**
Each time a workflow runs, Softr counts the **actions** that execute. Triggers and flow control steps (like **Wait**, **Branch**, **Filter**, and **Bulk actions**) don't count toward usage. Some actions (for example, sending emails) may use more than one execution, depending on the integration.
### **Other pricing notes**
- **Utilities:** Advanced actions like **Run code**, **Extract PDF**, and **Scrape webpage** are available on paid plans.
- **Webhook & API:** Available starting from the **Professional** plan and above.
- **AI credits:** Used for **AI Actions**. Business and Enterprise plans can also use their own API keys. Learn more about AI credits >
You can track your current usage and limits anytime in **Billing → Usage**, and view all plan allowances on the [**Pricing**](https://www.softr.io/pricing) [page](https://www.softr.io/pricing). Workflow actions reset each month.
## **FAQ**
### **Can I connect Workflows to AI Agents?**
- **AI Actions (in Workflows)** use Softr built-in AI integrations (or OpenAI or Anthropic API keys) to write, summarize, categorize, or run a custom prompt **inside** your workflow.
- **Database AI Agents (in Databases)** classify, summarize, enrich, or validate records when data is created or updated in your Softr Database.
**How they work together:**
A Database AI Agent can enrich or classify a new record (e.g., set `Sentiment = positive/negative`). Your **workflow** can then **branch** based on that value—send a follow-up email if negative, post a Slack kudos if positive.
**Both** AI Actions and Database AI Agents consume **AI credits**. [Learn more →](https://docs.softr.io/workspace-and-billing/jZP6yaeXMiJCuB6HhS4xKd/ai-credits/5VRMhf7Q6xvy7AJqyiQLx5)
### **Do I need any coding experience to build workflows?**
No. The Workflow builder is fully visual. You can drag and drop triggers and actions, use a template, or use the AI Co-builder to generate a workflow from plain-language instructions. A "Run Code" action is available for more advanced workflow needs.
### **Can I build workflows that connect to external tools?**
Yes. Use the **Call API** action to push or fetch data from any external system, or the **Webhook trigger** to start workflows from other apps like Stripe or HubSpot.
### **Are workflows available on the Free plan?**
Yes. You can build workflows on all plans. The Free plan includes 7 days of run history and limited step executions. Higher-tier plans include longer history and more generous limits. See the Pricing page for full details.
### **Do unused Workflow actions rollover?**
No, unused workflow actions do not rollover from one month to the next, however, the workflow action monthly limit is reset back to your full plan allowance.
---
# Trigger Types
Source: https://docs.softr.io/workflows/trigger-types
# Summary
Triggers define when a workflow runs. Every workflow starts with exactly one trigger — the event or condition that kicks off the sequence of actions. Softr Workflows supports three categories of triggers: Softr-native triggers, built-in triggers, and integration triggers from third-party services.
---
## Softr Triggers
Softr-native triggers respond to events inside your Softr account — your databases, apps, and email inbox.
### Softr Databases
Database triggers fire based on changes to records in your Softr databases. All database triggers are **Instant** — they fire immediately when the event occurs, with no polling delay.
#### Record added
Fires when a new record is created in the selected table.
**Configuration:**
1. **Account** — Select your Softr Databases account
2. **Database** — Choose the database
3. **Table** — Choose the table to watch for new records
4. **Conditions** (optional) — Add field-level conditions to only trigger when the new record matches specific criteria
**When to use:** Kick off onboarding sequences when a new client record is created, or notify your team in Slack when a new lead is added.
---
#### Record deleted
Fires when a record is removed from the selected table.
**Configuration:**
1. **Account** — Select your Softr Databases account
2. **Database** — Choose the database
3. **Table** — Choose the table to watch for deletions
4. **Conditions** (optional) — Filter by field values on the record being deleted
**When to use:** Log deleted records to an audit table, or send a confirmation email when a user cancels a subscription.
---
#### Record updated
Fires when any field on an existing record changes.
**Configuration:**
1. **Account** — Select your Softr Databases account
2. **Database** — Choose the database
3. **Table** — Choose the table to watch
4. **Conditions** (optional) — Scope the trigger to specific field values (e.g., only fire when `Status` is `"Active"`)
> **Tip:** If you only want to react to a specific field changing, combine this trigger with a [Filter](./workflows-advanced-concepts#filter) action at the start of your workflow to check the exact field.
**When to use:** Sync record changes to a Google Sheet, or send a notification when a project's status is updated.
---
#### Record meets conditions
Fires when a record matches a set of field-level conditions you define — useful when you care about a specific state, not just any update.
**Configuration:**
1. **Account** — Select your Softr Databases account
2. **Database** — Choose the database
3. **Table** — Choose the table
4. **Conditions** — Define one or more field conditions (e.g., `Status` **Is** `"Approved"`)
**When to use:** Trigger an approval email exactly when a record's status field is set to `"Approved"`, rather than on every update.
---
#### Record enters the view
Fires when a record appears in a saved database view — for example, when a filter on the view is satisfied.
**Configuration:**
1. **Account** — Select your Softr Databases account
2. **Database** — Choose the database
3. **Table** — Choose the table
4. **View** — Select the saved view to watch
**When to use:** Automate actions tied to view-based segments, such as sending a follow-up email to all records that enter a "High Priority" filtered view.
---
### Softr Apps
App triggers fire based on user activity within your published Softr applications. These triggers fall into two distinct execution models: **Synchronous** (Interactive) and **Polling** (Background).
#### Synchronous Triggers (Interactive)
Synchronous triggers maintain a live connection between the user's browser and the workflow runner. **Only these triggers support the [Show Wait Screen](./workflows-advanced-concepts#managing-the-loading-state) and [End User Interactions](./workflows-advanced-concepts#closing-the-loop-with-ui-feedback) actions.**
##### Submit form
Fires instantly when a user submits a form block in your Softr app.
**Configuration:**
- **Application** — Select the Softr app
- **Form Block** — Select the specific form block to watch
**When to use:** Process form data with AI or custom logic and show an immediate success toast or redirect.
##### Run custom workflow
Fires instantly when a user clicks a button configured with the "Run custom workflow" action.
**Configuration:**
- **Application** — Select the Softr app
- **Button** — Map the workflow to a specific button in your interface
**When to use:** Create high-UX features like "Upvote", "Approve", or "Generate Summary" that provide instant visual feedback.
##### Record created (UI)
Fires when a user creates a record through a List block's 'Add' action inside the app.
**When to use:** Redirect a user to a custom onboarding page immediately after they create their first project.
##### Record updated (UI)
Fires when a user edits an existing record through a List block's 'Edit' action inside the app.
**When to use:** Validate an update and show a confirmation loading screen while a backend sync occurs.
---
#### Polling Triggers (Background)
These triggers use a background service to check for updates approximately every **1 minute**.
##### User added
Fires when a new user account is created in the selected Softr app.
**When to use:** Send a welcome email, create a corresponding record in your database, or add the user to a Slack channel.
##### Comment added
Fires when a user posts a comment anywhere in the selected Softr app.
**When to use:** Notify a team member when a client leaves a comment.
---
### Softr Email
> **Note:** The Softr Email trigger requires a **Basic plan** or higher.
#### Email received
Fires instantly when an email arrives at your Softr inbound email address.
**Execution type:** Instant
**Configuration:**
- No additional fields required. Softr provides a unique inbound email address for your account. Any email sent to that address activates workflows using this trigger.
**When to use:** Parse incoming email notifications from other services, route support emails into your database, or trigger follow-up workflows when a specific type of email arrives.
---
## Built-in Triggers
Built-in triggers are general-purpose triggers that don't depend on a specific app or integration.
### Webhook
> **Note:** The Webhook trigger requires a **Professional plan** or higher.
**Execution type:** Instant
Softr auto-generates a unique POST endpoint URL for each workflow that uses this trigger. Any external service or application can send an HTTP POST request to that URL to start the workflow.
**Configuration:**
- **Webhook URL** — Auto-generated; copy and paste into the external service
- **CORS origins** — (Optional) Restrict which domains can send requests to this endpoint
**Request body:** The trigger reads the body according to its `Content-Type` header:
| Content-Type | Where it arrives |
| ------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `application/json`, or no usable `Content-Type` | Parsed into `body` |
| `application/x-www-form-urlencoded` | Each field in `body` |
| `multipart/form-data` | Text fields in `body`, each uploaded file in `files` |
| Text: `text/plain`, `text/xml`, `application/xml`, ... | `body` as a string (decoded with the `charset` of the `Content-Type`, UTF-8 by default), or parsed like JSON when the whole text is valid JSON |
| Anything else: `application/pdf`, `image/png`, `application/octet-stream`, ... | The whole body as one file in `files` |
A file sent as the raw body takes its name from the `Content-Disposition` header when the sender sets one (for example `attachment; filename="invoice.pdf"`), and is otherwise named `file` with an extension that matches the content type, such as `file.pdf`, or `file.bin` when the content type has no usual extension. For example, this request starts the workflow with the PDF in `files`:
```bash
curl --data-binary @invoice.pdf -H "Content-Type: application/pdf"
```
Each file, uploaded or sent as the raw body, can be up to 10 MB. A larger raw body is rejected with HTTP 400 and the message `Webhook request body exceeds the maximum file size of 10 MB`.
A request without a `Content-Type` header, or with one that cannot be read, must carry JSON. Any other body is rejected with HTTP 400 and the message `Webhook request has no usable Content-Type header and the body is not JSON. Set Content-Type to the body's type, such as application/pdf or text/plain.` A request that declares JSON but sends invalid JSON gets `Malformed JSON webhook body`.
> **Tip:** Use the Webhook trigger to start workflows from Softr button clicks, form submissions on external sites, or any service that supports outbound webhooks.
**When to use:** Connect Softr Workflows to any tool that supports webhooks — Stripe payment events, Typeform submissions, Shopify orders, or your own application.
---
### One-time schedule
Runs a workflow exactly once at a date and time you specify.
**Execution type:** Scheduled (runs once)
**Configuration:**
- **Date/time picker** — Select the exact date and time for the single run
**When to use:** Schedule a one-off data migration, send a time-specific announcement email, or prepare data before a product launch.
---
### Recurring schedule
Runs a workflow repeatedly on a schedule you define.
**Execution type:** Scheduled (repeating)
**Configuration:**
1. **Frequency** — Choose from:
- Every 1 minute
- Every 5 minutes
- Every 10 minutes
- Every 15 minutes
- Every 20 minutes
- Every 30 minutes
- Every hour
- Every day at...
- Every week at...
- Every month at...
2. **Time** — Time picker (shown for daily, weekly, and monthly frequencies)
3. **Timezone** — Timezone selector (defaults to Los Angeles time)
4. **Run on weekends?** — Toggle to include or skip Saturday and Sunday runs
**When to use:** Send a daily digest email, run a nightly data sync, generate a weekly report, or poll an external system on a regular interval.
---
## Integration Triggers
Integration triggers connect Softr Workflows to third-party services. Softr Tables, Calendly, Attio, and Zoho CRM are **Instant**, while other services use background polling.
### Softr Tables
Softr Tables triggers fire instantly since version 1.1.0, ensuring high performance.
| Event | Execution type |
| -------------- | -------------- |
| Record created | **Instant** |
| Record updated | **Instant** |
| Record deleted | **Instant** |
---
### Airtable
| Event | Execution type |
| -------------- | ---------------- |
| Record updated | 1-minute polling |
**Configuration:** Requires a connected Airtable account. Select the base and table to watch.
**When to use:** Mirror Airtable updates into a Softr database, or trigger notifications when a record's status changes in Airtable.
---
### Gmail
| Event | Execution type |
| -------------- | ---------------- |
| Email received | 1-minute polling |
**Configuration:** Requires a connected Gmail account (OAuth). Optionally filter by sender, subject, or label.
**When to use:** Start a workflow when a specific sender emails you, log incoming emails to your database, or route emails to different team members based on content.
---
### Outlook
| Event | Execution type |
| -------------- | ---------------- |
| Email received | 1-minute polling |
**Configuration:** Requires a connected Outlook account (Microsoft 365, Outlook.com or Hotmail). Pick the **Folder** to watch; it defaults to the Inbox. Optionally fill **From** with one or more sender addresses, separated by commas, to run only for emails from them.
> **Tip:** The trigger runs once for each email that arrives in the folder after the workflow is turned on. Emails already in the folder and emails that land in its subfolders do not run it — pick the subfolder itself for those. An email moved in from another folder runs it only if it was received within a few minutes of the newest email the trigger has seen. Non-inline attachments are passed on as files.
> **Note:** Outlook connections made before this trigger existed can send email but not read it. If the folder list or the test shows _"Softr can't read emails with this Outlook connection yet. Reconnect your Outlook account to allow reading emails."_, reconnect the same account; workflows that use it keep working.
**When to use:** Start a workflow when an order confirmation or a support request arrives, log incoming emails to your database, or route emails from specific senders to the right team.
---
### Google Sheets
| Event | Execution type |
| --------- | ---------------- |
| Row added | 1-minute polling |
**Configuration:** Requires a connected Google account (OAuth). Select the spreadsheet and sheet to watch.
**When to use:** Trigger workflows when a new form response is appended to a Sheet, or when a team member adds a row manually.
---
### Notion
| Event | Execution type |
| -------------- | ---------------- |
| Record created | 1-minute polling |
| Record updated | 1-minute polling |
**Configuration:** Requires a connected Notion account (OAuth). Select the database to watch.
**When to use:** Sync Notion database entries to Softr, or trigger notifications when a Notion page is updated.
---
### HubSpot
| Event | Execution type |
| -------------- | ---------------- |
| Record created | 1-minute polling |
| Record updated | 1-minute polling |
**Configuration:** Requires a connected HubSpot account (OAuth). Select the object to watch — Contacts, Companies, Deals, Tickets, or any other supported object, including custom objects.
**When to use:** Notify your team when a new lead lands in HubSpot, add new CRM records to a Softr database, or act on a deal stage change.
---
### Calendly
| Event | Execution type |
| ----------------- | -------------- |
| Invitee Scheduled | Instant |
| Invitee Canceled | Instant |
| Invitee No Show | Instant |
**Configuration:** Requires a connected Calendly account (OAuth).
> **Tip:** Calendly triggers are Instant — they fire via webhook as soon as the event occurs in Calendly, making them ideal for time-sensitive automations like sending immediate confirmation emails or creating records right after a meeting is booked.
**When to use:** Create a database record when someone books a meeting, send a reminder sequence when a meeting is scheduled, or log no-shows for follow-up.
---
### Attio
| Event | Execution type |
| -------------- | -------------- |
| Record created | **Instant** |
| Record updated | **Instant** |
| Record deleted | **Instant** |
| Task created | **Instant** |
**Configuration:** Requires a connected Attio account. Optionally scope record triggers to a single object (People, Companies, Deals, or a custom object); leave empty to fire for all objects.
> **Tip:** Attio triggers are Instant — they fire via webhook as soon as the change happens in Attio. **Record updated** fires once per changed attribute.
**When to use:** Sync new Attio records into a Softr database, notify a team when a deal is updated, or kick off a follow-up workflow when a task is created.
### Zoho CRM
| Event | Execution type |
| -------------- | -------------- |
| Record created | **Instant** |
| Record updated | **Instant** |
| Record deleted | **Instant** |
**Configuration:** Requires a connected Zoho CRM account. Each trigger watches one module — Leads, Contacts, Accounts, or Deals.
> **Tip:** Zoho CRM triggers are Instant — Zoho notifies Softr as soon as the change happens. The output carries the record ID; **Record updated** also lists the changed fields and their new values. Chain **Get record** to read the full record. A bulk edit or import starts one run per affected record.
**When to use:** Notify a team when a lead is created, act on a deal stage change, or keep your Softr database in step with the CRM when records are deleted.
---
## Trigger Comparison Table
| Trigger | Category | Execution type | Plan requirement |
| ----------------------- | --------------- | --------------------- | ---------------- |
| Record added | Softr Databases | Instant | Any |
| Record deleted | Softr Databases | Instant | Any |
| Record updated | Softr Databases | Instant | Any |
| Record meets conditions | Softr Databases | Instant | Any |
| Record enters the view | Softr Databases | Instant | Any |
| User added | Softr Apps | 1-min polling | Any |
| Comment added | Softr Apps | 1-min polling | Any |
| **Submit form** | Softr Apps | Synchronous | Any |
| **Run custom workflow** | Softr Apps | Synchronous | Any |
| **Record created (UI)** | Softr Apps | Synchronous | Any |
| **Record updated (UI)** | Softr Apps | Synchronous | Any |
| Email received | Softr Email | Instant | Basic+ |
| Webhook | Built-in | Instant | Professional+ |
| One-time schedule | Built-in | Scheduled (once) | Any |
| Recurring schedule | Built-in | Scheduled (repeating) | Any |
| Record updated | Airtable | 1-min polling | Any |
| Email received | Gmail | 1-min polling | Any |
| Email received | Outlook | 1-min polling | Any |
| Row added | Google Sheets | 1-min polling | Any |
| Record created | Notion | 1-min polling | Any |
| Record updated | Notion | 1-min polling | Any |
| Record created | HubSpot | 1-min polling | Any |
| Record updated | HubSpot | 1-min polling | Any |
| Invitee Scheduled | Calendly | Instant | Any |
| Invitee Canceled | Calendly | Instant | Any |
| Invitee No Show | Calendly | Instant | Any |
| Record created | Attio | Instant | Any |
| Record updated | Attio | Instant | Any |
| Record deleted | Attio | Instant | Any |
| Task created | Attio | Instant | Any |
| Record created | Zoho CRM | Instant | Any |
| Record updated | Zoho CRM | Instant | Any |
| Record deleted | Zoho CRM | Instant | Any |
---
---
# Advanced Concepts
Source: https://docs.softr.io/workflows/advanced-concepts
# Workflows: Advanced Concepts
This page covers the patterns and techniques for building non-trivial workflows: referencing data across steps, conditional logic, data transformation, AI-powered automation, human-in-the-loop approvals, and more.
---
## Referencing Data Between Steps
Most workflow actions need data from earlier steps: the record that triggered the workflow, a value returned by an AI action, a field from a database lookup. **Variables** are how you pass data from one step to the next.
**How it works:**
1. In any action's settings, click the **+** button to open the variable picker.
2. Browse the list of previous steps (the trigger and every action that ran before this one).
3. Select a field. Its value will be injected at runtime when the workflow runs.

_Variable picker showing outputs from a previous step_
You can combine variables with static text. For example, a Slack message might read: `A new bug was reported by [+ Trigger → email]: [+ Trigger → description]`.
**Where variables come from:**
- **Trigger data** - the record, form submission, or webhook payload that started the workflow. Available in every subsequent step.
- **Action outputs** - the result of any previous action. For example, an AI Categorize step outputs a `category` field; a Get Record step outputs all the record's fields.
- **Loop variables** - inside a Loop, use `{loopVariables.fieldName}` to access the current item's data. See the Loop section below.
> **Tip**
>
> Every action produces outputs that become available as variables in later steps - including AI actions. This is what makes it possible to chain an AI classification into a Branch condition or a record update.
**Example:** A form submission triggers a workflow. Step 1 uses the submitter's email from the trigger to look up their full user record. Step 2 sends a Slack message that combines the form's message field (`+` → Trigger → message) with the user's account plan from Step 1 (`+` → Step 1 → plan).
**Common Trigger Payloads:**
Different triggers provide different sets of variables at the start of your workflow. Understanding these helps you design better logic:
- **UI triggers (Submit form, Run custom workflow, Add record, Edit record):** Provide context about the app, including `applicationId`, `pageId`, and `blockId`. Triggers from list blocks also include the specific `record` object.
- **Softr Databases triggers:** Provide an `id` and a `fields` object containing all key-value pairs from the record.
- **Softr Apps data triggers (User added):** Provide rich user metadata including `fullName`, `credentials.email`, and `userGroups`, so you can branch based on permissions.
- **Webhooks & Calendly:** Pass the raw `body` of the event. Webhooks additionally provide `header` and `query` variables.
---
## Branch
The **Branch** action splits your workflow into two paths based on a condition.
- If the condition is **true**, the workflow follows the "yes" path.
- If the condition is **false**, it follows the "no" path.
This is the main way to build if/else logic without writing code.

_Branch action splitting the workflow into two paths based on an AI result_

_Using a variable from a previous step inside a Branch path_
**Example:** After a user submits a form, branch on whether their subscription plan is "Pro". If yes, send them a welcome email for Pro users. If no, send the standard welcome email.
Branches are especially powerful when combined with AI actions - see [AI + Branch Patterns](#ai--branch-patterns) below.
---
## Filter
The **Filter** action checks a condition and **stops the workflow** if the condition is not met.
Use it when you only want the workflow to continue for certain records or situations, and there's nothing to do in the "no" case.
**Example:** A workflow triggers on every new record in a Softr Databases table. Add a Filter at the start to stop the workflow if the record's "Status" field is not "Ready". Only "Ready" records will proceed through the rest of the workflow.

_Filter action stopping the workflow unless a condition is met_
Unlike Branch, Filter doesn't create two paths. It's an early exit.
---
## Loop
The **Loop** action runs a group of actions once for each item in a list.
**How it works:**
1. You point the Loop at an array of items (e.g. a list of records returned by a "Get Records" action).
2. The actions inside the loop run once per item.
3. Inside the loop, use `{loopVariables.fieldName}` to access the current item's data and `{loopCounter}` to know which iteration you're on.
4. After all items are processed, the workflow continues with the next action after the loop.

_Loop action iterating over a list of items from a webhook_

_Loop with actions inside: Enrich with AI and Add task run for each item_
**Example:** Fetch all "Pending" orders from a Softr Databases table, then loop over them and send each customer a status update email.
### Nested Loops
You can place a Loop inside another Loop to handle **lists within lists**.
**When to use it:** When each item in your outer list contains its own list of items that each need individual processing.
**Example:** You have a list of Tasks, and each Task has multiple Tags. You want to create one record per Task and Tag combination.
```
Loop Tasks
└── Loop Tags of this Task
└── Create record (Task + Tag)
└── Mark Task as checked
```
Here, if a task has 3 tags, the inner loop runs 3 times and creates 3 records for that task. The outer loop then moves on to the next task.
Nesting is not limited to two levels. You can nest further if your data structure requires it.
> **Tip**
>
> Be mindful of loop size. If you loop over a large list, every action inside the loop runs once per item - this affects both performance and your workflow action usage. Combine loops with Filters or conditions on your Get Records step to keep the list small.
---
## Transform Data
The **Transform Data** action lets you create new values using **formulas** - the same formula syntax available in Softr Databases. Use it to reshape, calculate, or extract data between steps without writing code.
**Common use cases:**
- **Arithmetic:** Increment a counter (`{vote_count} + 1`), calculate a total, compute a percentage
- **String manipulation:** Convert text to lowercase, concatenate fields, extract a substring
- **Date extraction:** Get the day of the week from a date (`WEEKDAY({submission_date})`), format a date for display
- **Conditional values:** Return different values based on a condition using `IF()` formulas
You name each output field yourself, and those names become available as variables in subsequent steps.

_Transform Data action using a `DATE_TIME_FORMAT` formula_
**When to use Transform Data vs. Run Custom Code:**
| | Transform Data | Run Custom Code |
| -------------------- | ------------------------------------------------------- | ------------------------------------------------------- |
| **Best for** | Simple calculations, string formatting, date operations | Complex logic, JSON parsing, multi-step transformations |
| **Syntax** | Softr formula language | JavaScript or Python |
| **Setup** | Zero setup - just write a formula | Define input variables, write code |
| **Plan requirement** | All plans | Paid plans |
**Example:** A user clicks an "Upvote" button, triggering a workflow. Step 1: Get the current record to read its `vote_count`. Step 2: Transform Data with formula `{vote_count} + 1`. Step 3: Update the record with the new value from Step 2.
---
## Run Custom Code
The **Run Custom Code** action executes **JavaScript** or **Python** inside your workflow. It's the escape hatch for logic that formulas can't express - parsing complex JSON, applying multi-step transformations, or computing values that would require deeply nested branches. The code can also call HTTP APIs with `fetch`, and the integrations you attach to the step authenticate those calls. The full reference, including the cryptography modules, is on the [Run Custom Code](/workflows/actions/run-custom-code) page.
**How inputs and outputs work:**
1. Define **input variables** in the action settings and map them to outputs from previous steps.
2. Inside the code, access these values through the input variables.
3. Return a value from your code - it becomes available as a variable in subsequent steps.
> **Tip**
>
> You don't need to write code from scratch. Click **Help me write code** in the code editor, describe what you want in plain language, and the AI assistant will generate the code for you.

_Run Custom Code action with JavaScript extracting a domain from an email_
> **Note**
>
> Run Custom Code is available on the [Pro plan and above](https://www.softr.io/pricing).
**Example:** A Call API step returns a complex JSON response with nested objects. Use Run Custom Code to extract just the fields you need (e.g., pull out `response.data.items[0].name`) and return them as clean variables for the next step.
---
## Call API
The **Call API** action makes an outgoing HTTP request to any REST endpoint. Use it to push data to external services, fetch information from third-party APIs, or connect with any system that supports HTTP.
**Key settings:**
- **Method:** GET, POST, PUT, PATCH, DELETE, or OPTIONS - or a variable, such as a `method` field the Webhook trigger received. A variable's value is read in any case (`put` is sent as PUT); an empty or unknown value fails the step with `Method is required, one of: [GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS]`.
- **URL:** The endpoint you're calling
- **Headers:** Authentication tokens, content type, and other metadata
- **Query parameters:** Key-value pairs appended to the URL
- **Request body:** The JSON payload to send (for POST, PUT, PATCH)

_Call API action configured with a GET request, authentication headers, and query parameters_
The response body is available as a variable in subsequent steps - you can reference individual fields from the JSON response, or use Run Custom Code to parse a complex response.
**Common HTTP status codes:**
| Code | Meaning | What to check |
| ---- | ------------ | -------------------------------------------------------------- |
| 200 | Success | Request worked as expected |
| 400 | Bad Request | Check your request body or parameters - something is malformed |
| 401 | Unauthorized | Check your API key or authentication headers |
| 404 | Not Found | Check the URL - the endpoint or resource doesn't exist |
> **Tip**
>
> **Call API vs. Webhook trigger:** Call API makes _outgoing_ requests to external services. The Webhook trigger does the opposite - it _listens_ for incoming requests from external services. One is an action, the other is a trigger.
> **Note**
>
> Call API is available on the Professional plan and above.
**Example:** When a form is submitted, use Call API to POST the submitter's name and email to your CRM's API. Map the form fields into the JSON body, set the `Authorization` header with your API key, and the CRM creates a new contact automatically.
---
## Structured Output from AI Actions
By default, AI actions return **freeform text** - useful for generating content, but difficult to use in Branch conditions or record updates because the format can vary.
Enable **Structured output** to get back a **JSON object with typed fields** instead. This makes the AI's response predictable and machine-readable, so you can reliably branch on it, store individual fields, or pass specific values to later steps.
**How to enable it:**
1. In any Custom Prompt AI action (Softr AI or bring-your-own-key), toggle **Structured output** on.
2. Provide a **JSON schema** that describes the fields and types you expect.

_Custom Prompt with Structured output enabled and a JSON schema example_

_The full JSON schema defining the expected output structure_
**Example schema** for categorizing customer feedback with a confidence score:
```json
{
"type": "object",
"properties": {
"category": {
"type": "string",
"enum": ["bug", "feature_request", "billing"]
},
"confidence": {
"type": "integer",
"description": "Confidence score from 0 to 100"
}
},
"required": ["category", "confidence"]
}
```
With this schema, the AI will always return exactly two fields - `category` and `confidence` - that you can reference in subsequent steps. No risk of the model returning unexpected text or varying its format between runs.

_Test result showing the structured output with subject and body fields_
> **Tip**
>
> If you only need simple classification into predefined categories, the **Categorize** AI action handles this without a JSON schema. Use **Custom Prompt + Structured output** when you need richer outputs (e.g., a category _and_ a confidence score, or multiple extracted fields).
---
## AI + Branch Patterns
Combining AI actions with Branches is one of the most common advanced patterns. The AI classifies or analyzes data, and the Branch routes the workflow based on the result.
### Basic AI routing
```
Trigger: Record added (feedback table)
→ AI Categorize (categories: Bug, Feature Request)
→ Branch: Is category "Bug"?
├── Yes → Post to #bugs Slack channel + Update record category
└── No → Post to #feature-requests channel + Update record category
```
The AI Categorize action outputs a `category` value. The Branch checks that value and sends the workflow down the appropriate path. Each path can notify a different team and update the original record with the assigned category.
### Confidence-gated routing
When you need more control, use a **Custom Prompt with Structured output** that returns both a category and a confidence score. Then branch on the confidence level:
```
Trigger: New support ticket
→ Custom Prompt AI (structured output: category + confidence)
→ Branch: Is confidence ≥ 70?
├── Yes → Auto-assign to team + Update record
└── No → Send interactive Slack message to reviewer
→ Branch on reviewer's response
├── Approve AI suggestion → Update record
└── Override → Update record with reviewer's category
```
This pattern lets AI handle the clear-cut cases automatically while routing ambiguous ones to a human. See [Human-in-the-Loop](#human-in-the-loop) below for more on the interactive review step.
---
## Choosing an AI Model
Softr workflows give you access to models from OpenAI, Anthropic, Google, Mistral, and DeepSeek. The right model depends on the complexity of the task - using the most powerful model for every step wastes credits and slows down your workflow.
| Task type | Recommended tier | Examples |
| ----------------------------------------------------------- | ---------------------- | -------------------------------------- |
| **Classification and routing** | Smaller, faster models | Claude Haiku, GPT-4.1 mini, GPT-5 nano |
| **Writing, summarization, data extraction** | Mid-tier models | Claude Sonnet, GPT-4.1, GPT-5 mini |
| **Complex reasoning, code generation, multi-step analysis** | Top-tier models | Claude Opus, GPT-5, o3 |
> **Tip**
>
> Start with the smallest model that could handle the task. Run a few tests and compare outputs. Only move to a more capable (and more expensive) model if quality is insufficient.

_AI model selector showing available models from multiple providers_
With **Softr AI**, you select from these models and usage is deducted from your AI credits. On Business and Enterprise plans, you can also **bring your own API key** for OpenAI, Anthropic, Google Gemini, Mistral, or DeepSeek to use your own account directly.
---
## Human-in-the-Loop
Some workflows should pause for human judgment rather than proceeding fully automatically. **Interactive actions** pause the workflow, send a message with response options, and resume based on the person's decision.
### When to use it
- **High-stakes decisions:** expense approvals, content publishing, permission changes
- **AI confidence is low:** the AI categorized something but isn't sure (see [Confidence-gated routing](#confidence-gated-routing) above)
- **Compliance requirements:** a human must review before certain actions proceed
### Slack Interactive Messages
The **Slack - Send Interactive Channel Message** and **Slack - Send Interactive Direct Message** actions send a Slack message that includes buttons. The workflow pauses until the recipient clicks a button, then resumes on the corresponding branch.
**Example - Expense approval workflow:**
```
Trigger: New expense report submitted (form)
→ AI validates expense category (structured output)
→ Slack interactive DM to manager:
"New expense: $500 for Software - submitted by Jane"
[Approve] [Reject] [Request more info]
→ Branch on manager's response:
├── Approve → Update record status to "Approved" + Notify submitter
├── Reject → Update record status to "Rejected" + Notify submitter
└── Request more info → Send email to submitter asking for details
```
The workflow stays paused until the manager clicks one of the buttons. This means the total execution time can be minutes, hours, or even days - the workflow will pick up right where it left off.
> **Tip**
>
> Interactive messages pair well with AI actions just before them. For instance, the AI can pre-fill a suggested category or summary in the message body, so the reviewer has context without opening the app.
---
## App-Triggered Workflows and UI Feedback
When a workflow is triggered by a user action inside your Softr app (clicking a button or submitting a form), the user is **waiting for a response**. These workflows are synchronous from the user's perspective, so you can control what they see while the workflow runs and after it completes.
### Wait Screen
The **Show Wait Screen** action displays a loading overlay in the app while the workflow processes. Add a custom message so the user knows what's happening (e.g., "Processing your vote..." or "Generating your report...").

_Wait screen showing a loading overlay in the app_
### End User Interactions
The **End User Interactions** action defines what happens after the workflow completes:
- **Toast message:** Show a success, info, warning, or error notification with a custom title and message
- **Navigation:** Stay on the current page, open a different page, open a record's details page, open an external URL, refresh the form, or close a modal
- **Reload blocks:** Toggle **Reload all blocks on current page** to refresh data displayed in the app - essential when your workflow updated a record that's visible on screen

_End User Interactions settings with toast message and navigation options_
**Example - Upvote button:**
```
Trigger: User clicks "Upvote" button (Run Custom Workflow)
→ Show Wait Screen ("Processing your vote...")
→ Get Record (using record ID from trigger)
→ Transform Data: vote_count + 1
→ Update Record with new vote count
→ End User Interactions:
Toast: "Vote recorded!" (success)
Reload all blocks on current page: Yes
```
The user sees a brief loading state, then a success message, and the vote count on screen updates immediately.
> **Note**
>
> Wait screens and End User Interactions only apply to workflows that start from a Softr Apps UI trigger: Submit form, Run custom workflow, Add record, or Edit record. They are not available for database triggers, schedule triggers, or webhooks.
---
## Selective Context Pattern
When using AI to process information from your database, a common mistake is dumping all your records into a single AI prompt. This is expensive, slow, and often produces worse results because the AI has too much noise to sift through.
The **selective context pattern** solves this by using a two-pass approach: a small AI model first selects which records are relevant, then only those records are passed to the main AI task.
**The pattern:**
```
Trigger: New task / request arrives
→ Get Records: Fetch all items from your knowledge base
→ Run Custom Code: Extract only the ID and title of each record
→ AI Custom Prompt (small model):
"Given this task: {task_description},
which of these items are relevant? {list_of_titles_and_ids}"
Structured output: array of selected IDs
→ Loop over selected IDs:
└── Get Record: Fetch the full content of each selected record
→ AI Custom Prompt (larger model):
"Complete this task: {task_description}
Using these resources: {full_content_of_selected_records}"
→ Store result
```
**Why this works:**
- **Pass 1** is cheap: a small model reads short titles and picks the relevant ones. This can process hundreds of items for minimal cost.
- **Pass 2** is focused: the larger model only receives the 3-5 records that actually matter, so it produces higher-quality output with less noise.
- **Total cost is lower** than sending everything to a large model in a single prompt.
**Example:** You have a database of 50 marketing insights (brand guidelines, product specs, audience research, content frameworks). A user requests a LinkedIn post about a specific product. Instead of sending all 50 insights to the AI, the workflow extracts their titles, asks a small model to pick the relevant ones (e.g., "LinkedIn post framework", "Product X specs", "Brand voice guidelines"), fetches those 3 full records, and passes them to a larger model to write the post.
---
# Run Custom Code
Source: https://docs.softr.io/workflows/actions/run-custom-code
# Run Custom Code
> **Applies to:** Run Custom Code 1.0.0, 1.1.0, 1.2.0
The **Run Custom Code** action runs **JavaScript** or **Python** inside your workflow. Use it for logic that formulas cannot express: parsing complex JSON, multi-step transformations, or calls to an API that has no dedicated action yet. The code can call HTTP APIs, and from version 1.2.0 the integrations you attach to the step authenticate those calls for you.
> **Note**
>
> Run Custom Code is available on the [Pro plan and above](https://www.softr.io/pricing).
> **Tip**
>
> You don't need to write code from scratch. Click **Help me write code** in the code editor, describe what you want in plain language, and the AI assistant generates the code for you.
## How the step works
1. **Data to use in the code**: name the values your code needs and map them to outputs of earlier steps. The code reads them from `inputData`.
2. **Integrations the code can call** (1.2.0 and later): attach the connected integrations the code may talk to. Each one gets an **alias**, a short name the code can use.
3. **Language** and **Code**: write the body of a function. Whatever you `return` becomes the output of the step, available to later steps as `body`.

_Run Custom Code action with JavaScript extracting a domain from an email_
## Reading input data
Every entry of **Data to use in the code** is a key of `inputData`. A value that is exactly one variable keeps its type: a number stays a number, a record stays an object, a list stays an array.
```javascript JavaScript
const email = inputData.email;
const items = inputData.items;
return { domain: email.split('@')[1], count: items.length };
```
```python Python
email = inputData['email']
items = inputData['items']
return {'domain': email.split('@')[1], 'count': len(items)}
```
## Returning a result
Return any JSON-compatible value: an object, a list, a string, a number or a boolean. Later steps reference it through the variable menu as `body`, or a field of it. A thrown error or a raised exception fails the step, and the message appears in the run details and in **Test your step**.
## Calling APIs with `fetch`
> **Applies to:** 1.2.0 and later
Both languages offer `fetch(url, options)`. It sends an HTTP request and returns a response object. In JavaScript you `await` it; in Python it is a plain call.
```javascript JavaScript
const res = await fetch('https://api.example.com/v1/contacts', {
method: 'POST',
headers: { 'X-Request-Source': 'softr' },
body: { email: inputData.email, name: inputData.name },
});
if (!res.ok) {
throw new Error(`Contact API answered ${res.status}: ${await res.text()}`);
}
return await res.json();
```
```python Python
res = fetch('https://api.example.com/v1/contacts', {
'method': 'POST',
'headers': {'X-Request-Source': 'softr'},
'body': {'email': inputData['email'], 'name': inputData['name']},
})
if not res.ok:
raise RuntimeError(f'Contact API answered {res.status}: {res.text()}')
return res.json()
```
**Options**
| Option | Meaning |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `method` | `GET` by default; `POST`, `PUT`, `PATCH`, `DELETE` and the others work as expected. |
| `headers` | An object of header names and values. |
| `body` | A string is sent as it is, as `text/plain` unless you set `Content-Type`. An object or a list is sent as JSON with `Content-Type: application/json`. In JavaScript, `URLSearchParams` is sent form-encoded. |
| `integration` | The alias of an attached integration that should authenticate this call. Needed only when two attached integrations share a host. |
**Response**
| Member | Meaning |
| ------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
| `status`, `ok` | The HTTP status code, and whether it is in the 200 range. |
| `headers` | The response headers with lower-case names. JavaScript: `res.headers.get('content-type')`. Python: `res.headers['content-type']`. |
| `text()`, `json()` | The body as text or parsed JSON. In JavaScript both are `await`ed. |
| `arrayBuffer()` (JavaScript), `bytes()` (Python) | The raw body, for binary answers. |
### Letting an integration authenticate the call
Attach the integrations your code talks to under **Integrations the code can call**. When the code calls a URL on the API host of an attached integration, the request carries that integration's credentials automatically. The code never sees a token, and nothing you paste into the code is needed.
```javascript JavaScript
// "salesforce" is attached to the step; the call to its API host is authenticated for you.
const res = await fetch(`${inputData.instanceUrl}/services/data/v60.0/sobjects/Account`, {
method: 'POST',
body: { Name: inputData.companyName },
});
return { created: res.ok, account: await res.json() };
```
```python Python
# Two attached integrations share the host api.hubapi.com; the alias picks the one to use.
res = fetch('https://api.hubapi.com/crm/v3/objects/contacts', {
'method': 'POST',
'body': {'properties': {'email': inputData['email']}},
'integration': 'sales_hubspot',
})
return res.json()
```
- The credentials are only added when the URL points at the provider's own API host. A call to any other host goes out without them, whatever alias you pass.
- You can attach every integration the **Call API** action can authenticate with. Database connections, Softr Databases, Softr Apps, Telegram and Trello cannot be attached, because their credentials have no HTTP header form.
- An alias is a short name of letters, digits and underscores, unique within the step. It defaults to the integration type, such as `salesforce` or `rest_api`.
- A REST API integration has no provider host, so it never authenticates a call by host alone. Name its alias in the call, and its headers go to whatever host that call names.
> **Warning**
>
> Do not put API keys or tokens into the code or into **Data to use in the code**. Connect the service as an integration and attach it to the step instead. The credential then stays out of your workflow definition and out of the run details.
### Calls without an integration
`fetch` also reaches any public host without an attached integration. The request is sent exactly as you wrote it, including any headers you set. Private networks, `localhost` and cloud metadata addresses are blocked.
## Calling HTTP APIs with `http` and `https`
> **Applies to:** 1.0.0, 1.1.0
>
> **Removed in:** 1.2.0. Use [`fetch`](#calling-apis-with-fetch) instead.
JavaScript can call HTTP APIs with the Node.js `http` and `https` modules. Return the promise of the result; the step waits for it.
```javascript
return new Promise((resolve, reject) => {
const url = 'https://api.example.com/v1/contacts?email=' + encodeURIComponent(inputData.email);
const req = https.request(url, { headers: { Authorization: 'Bearer ' + inputData.apiToken } }, (res) => {
let data = '';
res.on('data', (chunk) => (data += chunk));
res.on('end', () => resolve(JSON.parse(data)));
});
req.on('error', reject);
req.end();
});
```
Python code has no network access in these versions. In JavaScript, `localhost` and the cloud metadata addresses are blocked.
## Cryptography
Both languages come with a cryptography module. The code can hash values, compute and check HMAC signatures, and decrypt or verify data that a partner encrypted or signed with RSA.
### JavaScript: `crypto` and `Buffer`
> **Applies to:** 1.0.0, 1.1.0, 1.2.0
`crypto` is the Node.js `crypto` module: `createHash`, `createHmac`, `privateDecrypt`, `publicEncrypt`, `sign`, `verify`, `randomUUID` and the rest of it. `Buffer` converts between text, base64, hex and raw bytes.
```javascript
const decrypted = crypto.privateDecrypt(
{ key: inputData.privateKeyPem, padding: crypto.constants.RSA_PKCS1_PADDING },
Buffer.from(inputData.encryptedToken, 'base64'),
);
const signature = crypto.createHmac('sha256', inputData.signingSecret).update(inputData.payload).digest('hex');
return { token: decrypted.toString('utf8'), signature };
```
### Python: `rsa`
> **Applies to:** 1.0.0, 1.1.0, 1.2.0
`import rsa` gives you the API of the `rsa` package: `rsa.PrivateKey.load_pkcs1` and `rsa.PublicKey.load_pkcs1` read a PEM or DER key in PKCS#1 or PKCS#8 form, `rsa.decrypt` and `rsa.verify` accept the ciphertext or signature as base64 text or as bytes, and `rsa.encrypt`, `rsa.sign`, `rsa.DecryptionError` and `rsa.VerificationError` work as in the package. Padding is PKCS#1 v1.5.
```python
import rsa
key = rsa.PrivateKey.load_pkcs1(inputData['privateKeyPem'])
token = rsa.decrypt(inputData['encryptedToken'], key).decode()
return {'token': token}
```
> **Warning**
>
> Keep private keys and secrets out of the code. Pass them in through **Data to use in the code**, mapped from a place only the right people can read, such as a record in a table with restricted access. The code then stays readable, and the same key is not repeated in every step that needs it.
## Runtimes and limits
| | JavaScript | Python |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Runtime** | Node.js (1.0.0, 1.1.0); Node.js 24 (1.2.0 and later) | Python 3.11 (1.0.0, 1.1.0); Python 3.12 (1.2.0 and later) |
| **Available** | `crypto` (the Node.js `crypto` module: hashes, HMAC, RSA, AES, signatures, random values), `Buffer`, timers, promises, `JSON`, `Math`, `Date`, regular expressions. `http` and `https` (1.0.0, 1.1.0). `fetch`, `URL`, `URLSearchParams`, `TextEncoder`, `TextDecoder`, `structuredClone` and top-level `await` (1.2.0 and later) | `rsa` (RSA with PKCS#1 v1.5 padding, PKCS#1 or PKCS#8 keys), the standard modules `json`, `re`, `math`, `statistics`, `decimal`, `fractions`, `datetime`, `random`, and the common built-in functions such as `len`, `range`, `enumerate`, `zip`, `sorted`, `min`, `max`, `sum`, `str`, `int`, `float`, `dict`, `list`, `set`, `tuple`. `fetch`, class definitions, `isinstance`, `map`, `filter`, `bytes`, and the further modules `zoneinfo`, `time`, `calendar`, `secrets`, `collections`, `itertools`, `functools`, `operator`, `string`, `textwrap`, `unicodedata`, `difflib`, `html`, `base64`, `hashlib`, `hmac`, `uuid`, `struct`, `copy`, `heapq`, `bisect`, `typing`, `enum`, `dataclasses`, `csv`, `io` (`StringIO`, `BytesIO`), `urllib.parse` (1.2.0 and later) |
| **Not available** | `require`, `import`, `console` output, the file system, environment variables. In 1.0.0 and 1.1.0 also `fetch` and top-level `await`: return a promise instead | `open`, `print` output, `os`, `sys`, `subprocess`, `requests`, `urllib.request`, other third-party packages, attribute names that start with `__`. In 1.0.0 and 1.1.0 also class definitions, `isinstance`, `map`, `filter`, `bytes` and every module not listed above |
| Limit | 1.0.0, 1.1.0 | 1.2.0 and later |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| Run time of one step | JavaScript: a returned promise must settle within five seconds, or the step fails with **Async script timed out after 5000ms**. Python: three seconds; the step then fails with **Execution timed out**. | About two minutes; the step then fails with **Execution timed out**. |
| Synchronous JavaScript | Two seconds of code without a promise in between. | Two seconds of code without an `await` in between. |
| Python CPU time | Two of the three seconds. | Two seconds; waiting for `fetch` does not count. |
| Python memory | 256 MB. | 256 MB. |
| `fetch` calls | – | Up to 20 per second per run, and up to 10 open at the same time. |
| One `fetch` | – | The target must answer within 30 seconds, or the call fails. |
| Request body | – | Up to 5 MB per `fetch`; a bigger body fails before it is sent. |
| Response size | – | Up to about 6 MB per `fetch` response. |
## When something fails
- A **script error** fails the step with the message of the error or exception. Test the step to see it while you write the code.
- A **`fetch` error** (1.2.0 and later) is raised as an exception in your code, so you can catch it. Its message names the reason: a blocked host, an unknown alias, too many calls, or a target that did not answer.
- **Execution timed out**, **Async script timed out** and **Memory limit exceeded** name the limit the run hit. Split the work between steps, or narrow the data the step receives.
## Versions
Steps created with an earlier version of Run Custom Code keep working. Opening such a step in the workflow editor upgrades it to the current version; code that used `http` or `https` must switch to `fetch` then. The **Applies to** line at the top of this page names the versions the page covers. An **Applies to** line under a heading names the versions that section applies to; without one, a section applies to every version of the page. A **Removed in** line names the version that dropped that part, and a **Version history** block lists what changed inside it.
| Version | What changed |
| ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1.2.0 | `fetch` in both languages, and the integrations attached to the step authenticate the calls. Node.js 24 and Python 3.12. Class definitions and many more standard modules in Python, top-level `await` in JavaScript, about two minutes per run. `http` and `https` removed. |
| 1.1.0 | The same inputs and runtime as 1.0.0. |
| 1.0.0 | The first version. |
> **Tip**
>
> Building workflows as code? The [Softr CLI](/softr-cli) keeps every Run Custom Code step in a real `.js` or `.py` file next to the workflow definition, and a coding agent can write and test it for you.
---
# Send Notification
Source: https://docs.softr.io/workflows/actions/send-notification
# Send Notification
> **Applies to:** Send Notification 1.0.0, 1.1.0
Send notifications to your app users directly from a Softr Workflow. Notify users about new messages, status changes, task assignments, or any other event — as a push notification in their browser, in the app's notification inbox, or both.
## Overview
> **Version history**
>
> - Changed in 1.1.0: renamed from **Send Push Notification** to **Send Notification**, with a choice of channels.
The **Send Notification** action is a native Softr feature that lets you notify one or more specific users of your published app. It delivers through two channels:
- **Push** — appears in the user's browser or device notification center, even when they're not actively using your app. Ideal for time-sensitive updates.
- **In-app** (1.1.0 and later) — appears in the notification inbox inside your app, next to comment and mention notifications. It waits there until the user reads it, even if they weren't online when it was sent.
Each notification includes a **title**, **body**, and an optional **URL** to open when the user clicks it.
## Prerequisites
Before using the Send Notification action in a Workflow, enable the channel(s) you want to use in your app:
1. Open your Softr app and go to **Users → Notifications**.
2. For **Push**, enable push notifications for the device type(s) you want to support — **Desktop**, **Mobile**, or both. Use **Permission prompt** to customize the message that asks users to allow notifications.
3. For **In-app**, turn on **In-app notifications**. Use **Notification inbox** to customize the inbox button and texts — see [Notification Center](/add-and-manage-users/notification-center).
4. Publish your app.
Once push is enabled, users who visit your published app will be prompted to allow notifications in their browser. Only users who have granted permission will receive push notifications from your workflows.
In-app notifications need no permission from the user: a recipient sees them in the inbox after logging in to your app.
> **Note**
>
> In-app notifications are available on the Professional plan and above, and push notifications on the Business plan and above. If your plan doesn't include a channel, its setting shows a plan badge and can't be turned on.
## Settings
| Field | Description |
| :--------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **App** | The published app whose users will be notified. Defaults to the current app. |
| **Channels** (1.1.0 and later) | Where to deliver the notification: **Push**, **In-app**, or both. A new step has both selected. |
| **User email** | One or more users to notify. Recipients must be users of the selected application. Map a user email from an earlier workflow step, or provide multiple emails separated by commas. |
| **Notification title** | The notification heading (displayed in bold). Keep it short and clear. |
| **Notification body** _(optional)_ | The notification message text. Describe what happened or what action is needed. |
| **Open URL on click** _(optional)_ | The page to open when the user clicks the notification. Only URLs that start with your app's domain are accepted. Defaults to your app's home page if left empty. |
> **Warning**
>
> If a channel is not enabled for the selected app, the action shows a warning:
>
> - **"Push notification is not enabled for this app. Please enable it here."**
> - **"App notifications are not enabled for this app. Please enable it here."** (1.1.0 and later)
>
> The **here** link takes you directly to **Users → Notifications** in your app settings. Until the channel is enabled and the app is published, notifications on that channel are not delivered.
## Key Benefits
- **Instant delivery:** Push notifications appear in the user's browser or OS notification center in real time.
- **Nothing gets missed:** In-app notifications stay in the inbox until the user reads them.
- **No email required:** Reach specific users directly without sending an email.
- **Clickable deep links:** Drive users to a specific page or record by setting a URL in the notification.
- **Native to Softr:** No third-party service or API key required — notifications are built into Softr.
## Example Use Cases
| Use Case | Description |
| :------------------------- | :-------------------------------------------------------------------------------- |
| **Task assignment** | Notify a user when a new task is assigned to them in your project management app. |
| **Status change alert** | Alert a customer when their order or support ticket status is updated. |
| **New message or comment** | Let users know when someone replies to their post or leaves a comment. |
| **Approval required** | Prompt a manager to review and approve a pending request. |
| **Deadline reminder** | Send a reminder before a due date using a scheduled workflow trigger. |
## How to Add a Notification Action to a Workflow
1. Open your Softr workspace and go to **Workflows**.
2. Create a new workflow or open an existing one.
3. Add an action step, select **Softr Apps**, then choose **Send Notification**.
4. In the **Settings** panel on the right, pick the **App** and **Channels**, then configure the **User email**, **Notification title**, **Notification body**, and optionally **Open URL on click**.
5. Map dynamic values from earlier steps (e.g., use the triggered user's email as the recipient, or the record name in the notification body).
6. Test the action using the **Testing** tab — for push, make sure at least one user has subscribed to notifications in your published app.
7. Turn on your workflow.
> **Tip**
>
> To test push notifications, open your published app in a browser, allow notifications when prompted, then trigger the workflow. The notification will appear in your browser's notification center.
>
> To test in-app notifications, log in to your published app as the recipient and open the notification inbox after the workflow runs.
## Versions
Steps created with an earlier version of Send Notification keep working. The **Applies to** line at the top of this page names the versions the page covers. An item marked with a version applies from that version on; everything else applies to every version of the page. A **Version history** block under a heading lists what changed for that part.
| Version | What changed |
| ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1.1.0 | Renamed from **Send Push Notification** to **Send Notification**. Adds **Channels** (**Push**, **In-app**); a new step has both selected. A 1.0.0 step opened in the builder is upgraded to 1.1.0 with **Push** only, so it keeps sending exactly what it did before — add **In-app** to also reach the inbox. |
| 1.0.0 | The first version, as **Send Push Notification**: push only. |
---
# Integrations
Source: https://docs.softr.io/workflows/integrations/overview
# Workflows Integrations
Softr Workflows connect with third-party services so you can automate tasks across your stack. Add an integration as a trigger or as an action. In the **Select an action** window, the **Integrations** list shows every service. Use the search field to find one fast. Browse the integrations in the left menu to see what each one offers.

---
# ActiveCampaign integration
Source: https://docs.softr.io/workflows/integrations/activecampaign
Connect ActiveCampaign with your Softr applications to keep your CRM, lists, and deals in sync with everything happening inside your no-code app. Capture leads from forms, push sign-ups to contacts, tag subscribers based on user actions, and build member dashboards backed by live ActiveCampaign data — all without writing a line of code.
## Overview
The Softr ActiveCampaign integration links your Softr app directly to your ActiveCampaign account so customer data flows both ways. Whenever someone signs up, fills out a form, updates a record, or takes an action in your app, you can create or update contacts, deals, accounts, and tags in ActiveCampaign automatically — and pull ActiveCampaign records back into Softr lists and detail pages just as easily.
This makes ActiveCampaign a natural fit for Softr customer portals, lead capture sites, marketing automation triggers, and member dashboards. Use it to turn your Softr forms into a marketing funnel, give your team a self-serve dashboard of open deals, or let members see and update their own CRM record from inside your app.
## Available Actions
### Contact
- **Create contact** — add a new contact in ActiveCampaign, optionally upserting if the email already exists. Supports first/last name, phone, and custom fields.
- **Update contact** — update an existing contact by ID.
- **Get contact** — retrieve a single contact by ID and pull their fields into your Softr app.
- **Delete contact** — delete a contact by ID.
- **List contacts** — search and list contacts with filters for email, name, list, tag, status, and creation date.
- **Add contact to list** — subscribe a contact to a list.
- **Remove contact from list** — unsubscribe a contact from a list.
- **Add tag to contact** — apply a tag to a contact.
- **Remove tag from contact** — remove a tag using the contact-tag link ID returned by Add tag.
### Deal
- **Create deal** — add a new deal with title, value, currency, contact, pipeline, stage, and owner.
- **Update deal** — change any field on an existing deal.
- **Get deal** — retrieve a deal by ID.
- **Delete deal** — delete a deal by ID.
- **List deals** — search and list deals with filters for pipeline, stage, owner, and status.
- **Add deal note** — append a note to a deal.
### Account
- **Create account** — add a new account with name, website URL, and custom fields.
- **Update account** — update an existing account by ID.
- **Get account** — retrieve an account by ID.
- **Delete account** — delete an account by ID.
- **List accounts** — search and list accounts.
### Tag & List
- **Create tag** — create a new contact or template tag.
- **List tags** — search and list available tags.
- **List lists** — list the lists in your ActiveCampaign account.
## Key Benefits
- **No-code CRM and marketing automation:** Wire your Softr forms, sign-ups, and record actions to ActiveCampaign visually — no developers, no Zapier zaps to maintain.
- **Two-way data flow:** Push new contacts and deals into ActiveCampaign and pull them back into Softr lists and detail pages, all from the same workflow builder.
- **Built for customer portals:** Give members a branded Softr experience while your team continues to run automations in ActiveCampaign — both sides stay in sync.
- **Granular segmentation:** Apply and remove tags, subscribe and unsubscribe from lists, and update custom fields based on actions inside your Softr app.
- **Built-in rate limiting:** Softr respects ActiveCampaign's 5 requests/second limit so your automations stay reliable as you scale.
## Example Use Cases
| Use Case | Description |
| :----------------------------- | :-------------------------------------------------------------------------------------------------------------------------------- |
| **Lead capture forms** | Turn Softr form submissions into new ActiveCampaign contacts and deals, complete with source attribution and custom fields. |
| **Member sign-up sync** | When a new user signs up to your Softr portal, automatically create a matching contact in ActiveCampaign and subscribe to a list. |
| **Self-serve customer portal** | Let members view and update their own ActiveCampaign contact record from inside a Softr app. |
| **Tag-based segmentation** | Tag contacts in ActiveCampaign based on Softr actions — clicking a CTA, completing onboarding, upgrading a plan. |
| **Internal sales dashboard** | Build a Softr admin tool that lists open deals from ActiveCampaign, with one-click updates back to the CRM. |
| **Account-based selling** | Sync companies as ActiveCampaign accounts and link them to contacts and deals for full account-based workflows. |
## How to Connect Softr with ActiveCampaign
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add an ActiveCampaign action.
3. Click **Connect to ActiveCampaign** to open the credentials form.
4. In a separate tab, log in to your ActiveCampaign account, go to **Settings → Developer**, and copy your **API URL** (looks like `https://your-account.api-us1.com`) and your **API Key**.
5. Paste both values into the Softr credentials form and save.
6. Choose the action you want to run — Create contact, Add deal note, List contacts, etc.
7. Map fields from your Softr forms, records, or earlier workflow steps to the matching ActiveCampaign fields. Dynamic dropdowns let you pick lists, tags, pipelines, stages, and owners from your account.
8. Save and activate your workflow.
---
# Airtable integration
Source: https://docs.softr.io/workflows/integrations/airtable
Connect Airtable with your Softr applications to turn your bases into the live backend for member portals, admin dashboards, and client-facing tools. Build workflows that read, create, and update Airtable records based on what your users do in Softr — no code required.
## Overview
The Softr Airtable integration lets your no-code app talk directly to your Airtable bases. Trigger record lookups, creations, and updates from form submissions, button clicks, status changes, or scheduled workflows, then surface the results back in Softr lists, detail pages, and member dashboards.
Whether you're building an internal CRM on top of an existing base, a client portal where customers manage their own records, or an admin tool that bulk-updates inventory and project data, Airtable acts as your single source of truth — and Softr becomes the polished interface your users actually log into.
## Available Actions
### Add record
Create a new record in any Airtable base and table when a user submits a form, signs up, or triggers an action in your Softr app.
### Get record
Look up a single Airtable record by ID and use its fields downstream in your workflow — to populate a confirmation page, send a personalized email, or feed another action.
### Get records
Query multiple records from a table with filters and sorting, perfect for powering Softr lists, member-specific views, or summary widgets.
### Update record
Edit a single Airtable record from inside Softr — update a status, mark a task complete, or change a customer's plan when the right event fires.
### Update records
Apply changes to many Airtable records at once, ideal for bulk admin actions like archiving, reassigning ownership, or rolling out a pricing change.
### Delete record
Remove a single record from a table when a user cancels, withdraws, or removes an item from their account.
### Delete records
Clean up multiple records in one step — useful for batch deletions from admin dashboards or scheduled cleanup workflows.
## Key Benefits
- **No-code simplicity:** Wire your Softr app to Airtable visually, with no scripting or API setup required.
- **Single source of truth:** Keep your data centralized in Airtable while giving users a polished, branded interface in Softr.
- **Real-time updates:** Reflect changes from Softr in Airtable instantly, so your team always sees the latest data.
- **Bulk and single-record operations:** Handle one-off edits and large-scale updates from the same workflow builder.
- **Member-facing or internal:** Power public sign-up flows, gated client portals, and back-office admin tools — all from the same Airtable base.
## Example Use Cases
| Use Case | Description |
| :------------------------------ | :--------------------------------------------------------------------------------------------------------------------------- |
| **Client intake portal** | Let new clients submit a Softr form and automatically create a record in your projects base, ready for your team to action. |
| **Member-managed directory** | Allow signed-in members to add, edit, and remove their own listings or profiles, with every change synced to Airtable. |
| **Internal CRM on Airtable** | Give your sales team a Softr dashboard to update deal stages, log notes, and reassign owners without opening Airtable. |
| **Bulk admin operations** | Build an admin view where ops can archive completed projects, reassign records, or apply pricing changes in one click. |
| **Status-driven notifications** | When a record's status changes in your Softr workflow, update Airtable and trigger downstream actions like emails or alerts. |
| **Scheduled data cleanup** | Run a recurring workflow that deletes stale records or refreshes outdated entries to keep your base tidy. |
## How to Connect Softr with Airtable
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add an Airtable action.
3. Click **Connect to Airtable** and authorize Softr to access your bases.
4. Pick the base and table you want to work with.
5. Map fields from your Softr forms, records, or previous workflow steps to the Airtable fields.
6. Set any filters or sorting if you're querying records, then preview the result.
7. Save and activate your workflow.
---
# Anthropic integration
Source: https://docs.softr.io/workflows/integrations/anthropic
Connect Anthropic with your Softr applications to bring Claude's AI writing, summarization, and classification into your workflows. Draft replies, condense long submissions, and route records automatically — all inside the apps your team and clients already use.
## Overview
The Softr Anthropic integration sends text from your workflows to Claude, Anthropic's family of AI models, and returns the result to use in any later step. Feed it form answers, database records, or content from previous actions, and get back polished writing, concise summaries, categories, or the response to any custom prompt you design.
In a typical Softr app, Anthropic slots in right after the things your users do: a client submits a brief through a form block, a member updates a record, a support request lands in your admin dashboard — and Claude turns that raw input into a summary, a draft reply, or a label your team can act on.
## Available Actions
### Custom prompt
Send your own prompt to Claude — with data mapped in from forms, records, or earlier steps — and use the response anywhere in your workflow.
### Write
Generate original text, from email drafts and product descriptions to personalized onboarding messages.
### Summarize
Condense long text — client briefs, meeting notes, support threads — into a short summary your team can scan.
### Categorize
Assign text to one of your predefined categories so submissions and records get routed to the right place automatically.
## Key Benefits
- **AI without code:** Add Claude to any workflow visually — no API calls, scripts, or prompt-engineering tooling to maintain.
- **Your own Anthropic account:** Connect with your API key and use your Anthropic plan, models, and usage limits directly.
- **Works on your app's data:** Map form answers, user profiles, and database records straight into prompts — and write the output back.
- **Consistent, structured output:** Use Categorize to get clean labels you can branch on, filter with, or store in a record.
## Example Use Cases
| Use Case | Description |
| :------------------------------ | :------------------------------------------------------------------------------------------------------- |
| **Triage form submissions** | Categorize incoming requests from a Softr form and route each one to the right team or status. |
| **Summarize client briefs** | When a client submits a project brief through your portal, save a Claude summary alongside the record. |
| **Draft support replies** | Generate a suggested reply for each new support request and post it to your admin dashboard for review. |
| **Personalized welcome emails** | When a new member signs up, write a tailored welcome message from their profile details and send it. |
| **Clean up user content** | Rewrite listing descriptions or member bios submitted by users into a consistent tone before publishing. |
## How to Connect Softr with Anthropic
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add an Anthropic action.
3. Click **Connect Anthropic** and paste your Anthropic API key. You can create one in the [Anthropic Console](https://console.anthropic.com) under **API Keys**.
4. Choose the model and write your instructions or prompt.
5. Map fields from your Softr forms, records, or previous workflow steps into the prompt inputs.
6. Save and activate your workflow.
---
# Apify integration
Source: https://docs.softr.io/workflows/integrations/apify
Connect Apify with your Softr applications to bring live web data into your no-code apps. Run web scrapers, monitor competitors, enrich leads, and build research dashboards — all triggered by what your users do in Softr.
## Overview
The Softr Apify integration lets you turn any Softr app into a frontend for the web. Trigger Apify Actors and tasks from form submissions, button clicks, or scheduled workflows, then pipe the scraped results straight back into your Softr lists, member dashboards, or admin tools.
Whether you're building a lead-research portal for your sales team, a price-monitoring dashboard for your operations team, or a public directory backed by live web data, Apify gives your Softr app access to thousands of pre-built scrapers and your own custom Actors — without writing a single line of code on the Softr side.
## Available Actions
### Run Actor
Start an Apify Actor — your own or one from the Apify Store — with custom JSON input. Optionally wait for the run to finish before continuing the workflow.
### Run Actor and Get Dataset
Run an Actor end-to-end and return the scraped items in a single step. Ideal when you want the results immediately available to the next workflow step.
### Get Last Actor Run
Fetch the most recent run of an Actor, optionally filtered by status. Useful for surfacing the latest results in a Softr list or for checking whether a recurring scrape has completed.
### Run Task
Trigger a saved Apify task using its preconfigured input. Perfect for canned scrapes you've tuned in the Apify Console.
### Run Task and Get Dataset
Run a saved task and return its output items in one step. The most common pattern for "user clicks a button → see scraped results in Softr" workflows.
### Fetch Dataset Items
Read items from any existing Apify dataset by ID. Use this to pull historical scrape results into a Softr list block or to paginate through large datasets.
### Get Key-Value Store Record
Retrieve a single record from an Apify key-value store. Useful for fetching screenshots, files, or structured payloads an Actor has saved alongside its dataset output.
## Key Benefits
- **No-code web data:** Add live web scraping to your Softr app without managing servers, browsers, or proxies.
- **Thousands of ready-made scrapers:** Tap into the Apify Store for pre-built Actors covering Google Maps, LinkedIn, Amazon, Instagram, Zillow, and more.
- **Bring your own Actors:** Run any custom Actor your team has built, with full control over input and output.
- **Real-time and scheduled:** Trigger scrapes on user actions in your app or as part of scheduled workflows.
- **Member-facing or internal:** Build self-serve research tools for your customers, or back-office dashboards for your team.
## Example Use Cases
| Use Case | Description |
| :---------------------------------- | :---------------------------------------------------------------------------------------------------------------------- |
| **Lead-research portal** | Let sales reps submit a Google Maps URL or LinkedIn search in a Softr form, then return enriched leads in a list block. |
| **Competitor price monitoring** | Run a scheduled scrape of competitor product pages and surface the latest prices in an internal Softr dashboard. |
| **Self-serve scraping for clients** | Sell scraping as a service through a member portal — clients submit a URL, get charged, and download results. |
| **Dynamic public directory** | Power a public-facing Softr directory (jobs, real estate, restaurants) with fresh data scraped on a schedule. |
| **Review and reputation tracking** | Pull Google Maps or Trustpilot reviews into an admin dashboard so your team can respond from inside Softr. |
| **AI-enriched lead workflows** | Chain Apify with an AI action — scrape a company site, then summarize it or draft an outreach email automatically. |
## How to Connect Softr with Apify
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add an Apify action.
3. Click **Connect to Apify** and paste your API token.
4. Your API token can be found in your Apify Console under **Settings → API tokens**.
5. Pick the Actor, task, dataset, or key-value store you want to use.
6. Map inputs from your Softr forms, records, or previous workflow steps to the Actor's JSON input.
7. Save and activate your workflow.
---
# Apollo integration
Source: https://docs.softr.io/workflows/integrations/apollo
Connect Apollo with your Softr applications to keep your sales pipeline in sync with what happens in your app. Turn form submissions into contacts, portal activity into deals, and follow-ups into tasks — automatically, without copying data between tools.
## Overview
The Softr Apollo integration lets your workflows create and update the core records of your Apollo workspace: contacts, accounts, deals, and tasks. When a lead comes in through your Softr app, the workflow can find or create the matching contact, attach it to an account, open a deal, and queue a task for your sales team — all in one pass.
In a typical Softr app, Apollo connects your customer-facing surfaces to your sales engine: lead-capture forms feed the pipeline, client portals update account data, and admin dashboards create follow-up tasks — so your CRM reflects reality without manual entry.
## Available Actions
### Create contact
Add a new contact to Apollo when a lead submits a form or a user signs up in your app.
### Find contact
Look up an existing contact to use or update its details in later steps — and avoid duplicates.
### Update contact
Keep contact details current when users edit their profile or new information arrives.
### Create account
Add a company account when a new organization signs up or is registered through your app.
### Update account
Refresh account details as company information changes in your Softr database.
### Create deal
Open a new deal when a qualified lead comes in or a client requests a quote.
### Update deal
Move deals through your pipeline — change stage, value, or owner — based on activity in your app.
### Create task
Queue a follow-up task for your sales team when a lead acts or a deal needs attention.
### Update task
Adjust or complete tasks automatically as the related work gets done.
## Key Benefits
- **Pipeline without data entry:** Leads, accounts, and deals create themselves from app activity — your team just follows up.
- **No duplicates:** Find contacts before creating them, so your Apollo workspace stays clean.
- **Full sales loop:** Cover the whole chain — contact, account, deal, task — from one visual workflow.
- **Faster follow-up:** Tasks land in Apollo the moment a lead acts, so no opportunity waits in an inbox.
## Example Use Cases
| Use Case | Description |
| :--------------------------- | :------------------------------------------------------------------------------------------------------------- |
| **Lead capture to pipeline** | When a lead form is submitted in your Softr app, create the contact, open a deal, and assign a follow-up task. |
| **Sign-ups to CRM** | Add every new app member as an Apollo contact, attached to their company account. |
| **Quote requests to deals** | When a client requests pricing through your portal, create a deal with the request details already filled in. |
| **Keep accounts current** | When a client updates company info in your portal, update the matching Apollo account automatically. |
| **Stage-driven tasks** | When a record's status changes in your admin dashboard, update the deal stage and create the next task. |
## How to Connect Softr with Apollo
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add an Apollo action.
3. Click **Connect Apollo** and paste your Apollo API key. You can create one in Apollo under **Settings → Integrations → API**.
4. Pick the action you need — contact, account, deal, or task.
5. Map fields from your Softr forms, records, or previous workflow steps to the action's inputs.
6. Save and activate your workflow.
---
# Attio integration
Source: https://docs.softr.io/workflows/integrations/attio
Connect Attio with your Softr applications to keep your CRM in sync with everything happening in your app — and to react instantly when something changes in Attio. Capture leads from forms, sync member sign-ups, create follow-up tasks, and kick off workflows the moment a record or task changes, all without code.
## Overview
The Softr Attio integration moves data both ways. From your Softr app into Attio: whenever a form is submitted, a user signs up, or a record changes, your workflow can create, update, or find records, add notes, and create or update tasks. From Attio back into Softr: webhook triggers fire your workflows the moment a record is created, updated, or deleted, or a task is created.
You choose which Attio object to work with — People, Companies, Deals, or any custom object — and map fields from your Softr forms, records, or previous workflow steps to Attio attributes. Softr automatically picks up your workspace's objects and attributes, including custom ones, so the setup matches your CRM exactly.
## Available Actions
### Create or update record
Add a new record to any Attio object, or update the existing one when a match is found — for example, by email address for people or by domain for companies. No duplicate checks needed: if the record exists, it's updated; if not, it's created.
### Create record
Add a brand-new record to any Attio object, with the attribute values you map from your app.
### Update record
Update an existing record by its ID — change only the attributes you choose, leaving the rest untouched.
### Find records
Search any Attio object for records that match the conditions you set, and use the results in later workflow steps.
### Get record
Retrieve a single record by its ID and use its attributes in later steps — for example, to pull the full details of the record that fired a trigger.
### Create note
Attach a note to a record in Attio — great for logging form answers, call summaries, or activity from your Softr app.
### Create task
Create a task in Attio, optionally with a deadline, an assignee, and a linked record, so follow-ups never slip.
### Update task
Update a task's deadline, completion status, assignee, or linked record by its ID.
## Available Triggers
### Record created
Starts a workflow when a new record is created in Attio. Optionally scope it to a single object.
### Record updated
Starts a workflow when a record is updated. Optionally scope it to a single object.
### Record deleted
Starts a workflow when a record is deleted. Optionally scope it to a single object.
### Task created
Starts a workflow when a new task is created in Attio.
## Key Benefits
- **No-code CRM automation:** Keep Attio up to date from your Softr app visually, without writing any code or touching an API.
- **Two-way sync:** Push data into Attio with actions, and react to changes in Attio with triggers — in one workflow builder.
- **No duplicates:** Create-or-update logic matches records by a unique attribute, so the same lead or customer is never added twice.
- **Works with your setup:** Standard and custom objects, custom attributes, selects, and statuses from your workspace all show up automatically.
- **Real-time:** Records, notes, and tasks land in Attio the moment something happens in your app — and Attio changes start your workflows instantly.
## Example Use Cases
| Use Case | Description |
| :---------------------------- | :---------------------------------------------------------------------------------------------------------- |
| **Lead capture forms** | Turn every Softr form submission into a person or company record in Attio, enriched with the form answers. |
| **Member sign-up sync** | Add new app users to Attio the moment they sign up, so sales and success teams see them right away. |
| **Client portal updates** | When a client updates their details in your portal, sync the changes to their Attio record automatically. |
| **Deal intake** | Create or update a deal in Attio when a request is submitted through your client-facing intake form. |
| **Log activity as notes** | Attach a note to the matching Attio record whenever a customer submits feedback or completes a step. |
| **Automatic follow-up tasks** | Create an assigned task in Attio when a new lead comes in, so someone always owns the next step. |
| **React to CRM changes** | When a record is created or updated in Attio, trigger a Softr workflow to notify a team or update your app. |
| **Enrich on trigger** | When a trigger fires, fetch the full record by its ID to read every attribute before notifying or updating. |
## How to Connect Softr with Attio
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add an **Attio** action (or trigger, if you want the workflow to start from an Attio event).
3. Click **Connect to Attio** and paste your access token. You can create one in Attio under **Workspace Settings → Developers → Access tokens**.
4. Pick the object you want to work with — People, Companies, Deals, or a custom object (and, for triggers, optionally scope to a single object).
5. Map fields from your Softr forms, records, or previous workflow steps to the action's inputs.
6. Save and activate your workflow.
---
# Bitly integration
Source: https://docs.softr.io/workflows/integrations/bitly
Connect Bitly with your Softr applications to create short, branded, trackable links automatically. Build workflows that shorten URLs the moment they're needed — when a record is added, a form is submitted, or a new member signs up — so every link you share is clean, on-brand, and measurable.
## Overview
The Softr Bitly integration links your no-code apps directly to your Bitly account. Whenever your workflow produces a URL worth sharing — a referral link, a campaign page, a document, a personalized signup link — you can automatically shorten it into a Bitlink with a title, tags, and the right Bitly group, then store or send the short link anywhere in your app.
Whether you're building a marketing dashboard, a partner portal, or a referral program, the Bitly integration turns long, unwieldy URLs into short links your users can actually share — with Bitly's click tracking behind every one of them.
## Available Actions
### Create link
Shorten any URL into a Bitlink with an optional title, tags, and Bitly group — all set dynamically from your Softr workflow. Groups are chosen from a live dropdown pulled straight from your connected Bitly account, and the short link comes back ready to store in a record, send in an email, or show to your users.
### Get link
Retrieve an existing Bitlink — its destination URL, title, tags, and archived state — so later workflow steps can reuse or display it.
### Update link
Rename a Bitlink, replace its tags, or archive and unarchive it, keeping your link library tidy as your Softr data changes.
### List links
Pull the Bitlinks in a group, optionally filtered by a search term — perfect for finding an existing short link before creating a new one, or for showing a campaign's links inside your app.
## Key Benefits
- **No-code simplicity:** Configure Bitly actions visually in Softr — no code required beyond the one-time access token setup.
- **Short links on autopilot:** Shorten URLs the moment your workflow runs, instead of pasting them into Bitly by hand.
- **Organized from the start:** File every link under the right Bitly group and tag it consistently, so campaigns stay tidy.
- **Trackable by default:** Every link created through your workflow is a Bitlink, so clicks are tracked in your Bitly dashboard automatically.
- **Share-ready output:** Use the short link immediately in the next workflow step — save it to a record, send it via email or Slack, or display it in your app.
## Example Use Cases
| Use Case | Description |
| :------------------------------- | :----------------------------------------------------------------------------------------------------------------- |
| **Referral link generator** | Create a personalized short link for each new member who signs up to your Softr app, and save it to their profile. |
| **Campaign link intake** | Let your marketing team submit long campaign URLs through a Softr form that returns a branded, tagged Bitlink. |
| **Record-based link shortening** | Shorten the URL field of every new record — listings, articles, products — and store the Bitlink alongside it. |
| **Event promotion** | When a new event is added in your Softr app, generate a short registration link ready for social media and email. |
| **Partner portal links** | Give partners tidy, trackable short links to share, generated automatically when their record is approved. |
| **Document sharing** | Shorten long file or page URLs before emailing them to clients, so messages stay clean and clicks stay measurable. |
## How to Connect Softr with Bitly
1. Open your Softr workspace and go to **Workflows**.
2. Create a new workflow or open an existing one, then add a Bitly action.
3. In the **Account** field, click **Add another account** and paste your Bitly **access token**.
4. To generate an access token, open Bitly and go to **Settings → Developer settings → API**, enter your password, and click **Generate token**.
5. Click **Save** — Softr verifies your token and connects the account.
6. Map the **Destination URL** from your Softr forms, records, or previous workflow steps, optionally pick a group and add a title or tags, then activate your workflow.
---
# Brevo integration
Source: https://docs.softr.io/workflows/integrations/brevo
Connect Brevo with your Softr applications to grow and manage your customer relationships automatically. Sync contacts, companies, and deals from your app into Brevo, and send emails that react to what your users do — all without code.
## Overview
The Softr Brevo integration lets your workflows manage the heart of your Brevo CRM — contacts, companies, and deals — and send email through your Brevo account. When someone signs up, submits a form, or updates a record in your Softr app, the workflow can create or update the matching contact, link it to a company, move a deal forward, and follow up by email.
In a typical Softr app, Brevo keeps marketing and sales in step with your product: sign-up forms feed your contact lists, client portals keep company records fresh, and status changes in your admin dashboard drive deal updates and customer emails.
## Available Actions
### Create contact
Add a new contact to Brevo when someone signs up or submits a form in your app.
### Get contact
Look up a contact's details to use in later workflow steps.
### List contacts
Retrieve contacts to power digests, syncs, or bulk follow-up steps.
### Update contact
Keep contact attributes current when users edit their profile or new data arrives.
### Delete contact
Remove a contact when a user unsubscribes or closes their account.
### Create company
Add a company record when a new organization joins your app.
### Update company
Refresh company details as information changes in your Softr database.
### Delete company
Remove company records you no longer need.
### Create deal
Open a deal when a qualified lead comes in or a client makes a request.
### Update deal
Move deals through your pipeline as things progress in your app.
### Delete deal
Clean up deals that are no longer relevant.
### Send email
Send an email through Brevo — confirmation, follow-up, or notification — with content built from your app's data.
## Key Benefits
- **CRM that updates itself:** Contacts, companies, and deals stay in sync with your app — no exports, no copy-paste.
- **Email included:** Send transactional and follow-up emails from the same workflow that updates the CRM.
- **Clean customer data:** Look up before you create, update when things change, and delete what's stale.
- **No-code setup:** Configure everything visually in the workflow editor, mapping in data from any step.
## Example Use Cases
| Use Case | Description |
| :---------------------------- | :------------------------------------------------------------------------------------------------------------- |
| **Sign-ups to your audience** | Add every new app member as a Brevo contact so campaigns and lifecycle emails reach them from day one. |
| **Lead forms to pipeline** | When a lead form is submitted, create the contact and open a deal with the request details attached. |
| **Portal edits to CRM** | When clients update their details in your portal, update the matching Brevo contact and company automatically. |
| **Status-driven emails** | When a record changes status in your admin dashboard, update the deal and send the customer a progress email. |
| **Account clean-up** | When a user cancels, delete or archive their contact and close out related deals in one workflow. |
## How to Connect Softr with Brevo
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a Brevo action.
3. Click **Connect Brevo** and paste your Brevo API key. You can create one in Brevo under **SMTP & API → API Keys**.
4. Pick the action you need — contact, company, deal, or email.
5. Map fields from your Softr forms, records, or previous workflow steps to the action's inputs.
6. Save and activate your workflow.
---
# Cal.com integration
Source: https://docs.softr.io/workflows/integrations/cal-com
Connect Cal.com with your Softr applications to turn scheduling into a fully automated part of your app — create, reschedule, and cancel bookings from your workflows, and start workflows the moment a meeting is booked, moved, cancelled, or ends. Build booking flows for onboarding, sales, and support without any manual back-and-forth.
## Overview
The Softr Cal.com integration moves data both ways. From your Softr app into Cal.com: whenever a form is submitted, a member signs up, or a record changes, your workflow can create a booking on the right event type, reschedule or cancel an existing one, or look bookings up to use in later steps. From Cal.com back into Softr: webhook triggers fire your workflows the moment a booking is created, rescheduled, or cancelled, or a meeting ends.
This pairs naturally with the way Softr apps are built — booking forms, member portals, and client-facing dashboards. Map fields from your Softr forms, records, or previous workflow steps to the booking's details, and react to real scheduling events to send follow-ups, update records, or notify your team.
## Available Actions
### Create booking
Create a booking on a Cal.com event type, using the attendee details and time you map from your app — great for turning a form submission into a confirmed meeting.
### Reschedule booking
Move an existing booking to a new time by its unique reference, with an optional reason that's shared with the attendee and host.
### Cancel booking
Cancel a booking by its unique reference, with an optional cancellation reason shown to the attendee and host.
### Get booking
Retrieve a single booking by its unique reference and use its details in later workflow steps — for example, to read the attendee and time of the booking that fired a trigger.
### List bookings
List bookings from Cal.com with optional filters, and use the results in the rest of your workflow.
## Available Triggers
### Booking created
Starts a workflow when a new booking is created in Cal.com.
### Booking rescheduled
Starts a workflow when a booking is moved to a new time in Cal.com.
### Booking cancelled
Starts a workflow when a booking is cancelled in Cal.com.
### Meeting ended
Starts a workflow when a Cal.com meeting has ended — perfect for post-call follow-ups.
## Key Benefits
- **No-code scheduling automation:** Create, move, and cancel bookings straight from your Softr workflows — no Zaps, scripts, or developer help required.
- **Two-way sync:** Push bookings into Cal.com with actions, and react to real scheduling events with triggers, all in one workflow builder.
- **Real-time follow-ups:** Kick off a workflow the instant a meeting is booked, rescheduled, cancelled, or ends — send confirmations, reminders, or thank-you messages automatically.
- **Personalized member experiences:** Turn form submissions, sign-ups, and record changes into confirmed meetings tied to the right event type and person.
- **Everything in one place:** Keep your bookings and your app's records in step, so your team always sees the latest scheduling activity.
## Example Use Cases
| Use Case | Description |
| :------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------ |
| **Booking from form submissions** | When a prospect submits a "Book a call" form, create a Cal.com booking on the right event type with the details they provided. |
| **Onboarding calls for new members** | Automatically book a kickoff meeting when someone signs up in your member portal, so onboarding starts without any manual steps. |
| **Post-meeting follow-ups** | When a meeting ends, trigger a workflow to send a thank-you email, log the call, or ask for feedback inside your app. |
| **Sync bookings to your records** | When a booking is created or rescheduled in Cal.com, update the matching record in your Softr app so your team always sees the latest time. |
| **No-show and cancellation handling** | When a booking is cancelled, trigger a workflow to notify the owner, free up the slot, or offer the attendee a new time. |
| **Reschedule from your app** | Let members move an existing meeting from their dashboard — reschedule the Cal.com booking and confirm the new time back to them. |
## How to Connect Softr with Cal.com
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a **Cal.com** action (or trigger, if you want the workflow to start from a Cal.com event).
3. Click **Connect to Cal.com** and give Softr permission to access your Cal.com account.
4. For an action, choose the event type and map the attendee details and time from your Softr form, record, or a previous workflow step.
5. For a trigger, pick the booking event you want to start the workflow — booking created, rescheduled, cancelled, or meeting ended.
6. Save and activate your workflow.
---
# Calendly integration
Source: https://docs.softr.io/workflows/integrations/calendly
Connect Calendly with your Softr applications to turn any user action into a personalized booking moment. Generate single-use scheduling links on the fly and deliver them to leads, members, or clients — without manual back-and-forth or copy-pasting calendar URLs.
## Overview
The Softr Calendly integration lets you create one-time scheduling links automatically, triggered by what happens inside your Softr app. Whenever someone fills out a form, signs up as a member, hits a milestone in your CRM, or clicks a button, Softr can mint a fresh Calendly link tied to the right event type and route it to the right person.
This unlocks tightly controlled booking flows for sales, success, and onboarding teams: every prospect or member gets a unique link that expires after one use, so you can pair scheduling with qualification, gating, or premium experiences across member portals, admin tools, and client-facing apps.
## Available Actions
### Create scheduling link
Generate a single-use Calendly scheduling link for a specific event type. Send it instantly via email, surface it in your Softr app, or pass it to the next step in your workflow.
## Key Benefits
- **No-code simplicity:** Configure the entire booking flow visually in Softr — no Zaps, scripts, or developer help required.
- **One link per person:** Single-use links keep your scheduling controlled, trackable, and personal — every recipient gets a unique URL.
- **Faster sales cycles:** Eliminate the back-and-forth by handing qualified leads a ready-to-book link the moment they raise their hand.
- **Personalized member experiences:** Reward sign-ups, plan upgrades, or form completions with an instant call-booking offer tailored to the right team member.
- **Real-time automation:** Generate and deliver links the second a trigger fires — no batch jobs, no delays.
## Example Use Cases
| Use Case | Description |
| :------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------- |
| **Demo booking from form submissions** | When a prospect submits a "Request a demo" form, generate a fresh Calendly link and email it back instantly so they can book on the spot. |
| **VIP onboarding for new members** | Reward new sign-ups in your member portal with a one-time link to book a kickoff call with their assigned account manager. |
| **Sales-team routing** | When a lead is qualified in your admin tool, mint a scheduling link tied to the right rep's calendar and surface it in the lead's record. |
| **Premium client booking gate** | Offer paying clients a unique, single-use call link from inside their dashboard — perfect for limited-availability advisory sessions. |
| **Renewal and check-in calls** | Trigger a personalized booking link whenever a customer's renewal date approaches, so success managers never miss a touchpoint. |
| **Application review interviews** | Generate a one-time interview link automatically when an application reaches the "approved" stage in your Softr admin app. |
## How to Connect Softr with Calendly
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add the **Create scheduling link** Calendly action.
3. Click **Connect to Calendly** and authorize Softr to access your Calendly account.
4. Pick the event type you want bookings to land on.
5. Map the invitee's name and email from your Softr form, member record, or previous workflow step.
6. Wire the generated link into the next step — send it via email, store it on a record, or display it in your app.
7. Save and activate your workflow.
---
# ClickUp integration
Source: https://docs.softr.io/workflows/integrations/clickup
Connect ClickUp with your Softr applications to turn forms, member actions, and record changes into tasks your team can actually work on. Build internal tools and client portals that stay in lockstep with your ClickUp workspace — without writing a single line of code.
## Overview
The Softr ClickUp integration lets you create, update, and read ClickUp tasks directly from your no-code app. Every form submission, button click, status change, or scheduled workflow can flow straight into the right ClickUp list — and ClickUp data can flow back into Softr lists and dashboards so your team always has the latest view.
This pairs naturally with the kinds of apps Softr customers build every day: client request portals where customer submissions become trackable tasks, internal admin tools to triage and assign work, and operational dashboards that surface project status to stakeholders without giving them a ClickUp seat.
## Available Actions
### Add record
Create a new ClickUp task from a Softr form submission, button click, or any other workflow trigger.
### Get record
Look up a single ClickUp task by ID to display its details inside your Softr app or use it later in the workflow.
### Get records
Pull a list of ClickUp tasks into a Softr list block, dashboard, or admin view — perfect for showing project progress to clients or teammates.
### Update record
Update a single ClickUp task — change its status, assignee, due date, or any other field — when something happens in your Softr app.
### Update records
Update many ClickUp tasks at once, ideal for bulk status changes, reassignments, or syncing field values across a project.
### Delete record
Remove a single ClickUp task from your workspace as part of a workflow.
### Delete records
Clean up multiple ClickUp tasks in one step when records are archived, projects close out, or duplicates need to be removed.
## Key Benefits
- **No-code task automation:** Wire ClickUp into your Softr app visually — no scripts, no API calls to manage.
- **Two-way sync:** Push tasks into ClickUp when users act in your app, and surface ClickUp data back inside Softr lists and dashboards.
- **Client-friendly project tracking:** Give customers a polished Softr portal to submit and follow requests, while your team works in ClickUp behind the scenes.
- **Bulk operations built in:** Update or delete many tasks at once to keep large projects clean without manual upkeep.
- **Always in sync:** Status changes, new requests, and field updates flow through automatically, so nothing falls through the cracks.
## Example Use Cases
| Use Case | Description |
| :--------------------------------- | :------------------------------------------------------------------------------------------------------------------ |
| **Client request portal** | Let customers submit briefs, support tickets, or change requests in a Softr form — each one becomes a ClickUp task. |
| **Internal project dashboard** | Surface live ClickUp tasks inside a Softr list block so non-ClickUp users can see project status at a glance. |
| **Status updates from your app** | Change a record's status in Softr and update the matching ClickUp task automatically — no double entry. |
| **Member-driven onboarding tasks** | When a new member signs up, create a checklist of onboarding tasks in ClickUp for the success team. |
| **Bulk project cleanup** | Archive or delete dozens of tasks at once when a project closes or stale items pile up in a list. |
| **Approvals that update ClickUp** | An admin clicks Approve in Softr, and the linked ClickUp task moves to "In Progress" with the right assignee. |
## How to Connect Softr with ClickUp
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a ClickUp action.
3. Click **Connect to ClickUp** and authorize the workspace you want to use.
4. Pick the workspace, space, and list you want to work with.
5. Map fields from your Softr forms, records, or previous workflow steps to the ClickUp task fields (name, description, assignee, status, due date, custom fields).
6. Save and activate your workflow.
---
# Coda integration
Source: https://docs.softr.io/workflows/integrations/coda
Connect Coda with your Softr applications to bring your docs and tables to life inside the tools you build. Pull rows from any Coda table into Softr lists, dashboards, and member portals — and keep your no-code app and your Coda workspace working from the same source of truth, without writing a single line of code.
## Overview
The Softr Coda integration lets you read rows from your Coda tables directly inside your no-code app. Form submissions, member actions, scheduled runs, and other workflow triggers can fetch the right rows from Coda so your app always reflects what your team is tracking.
This fits naturally with the kinds of apps Softr customers build every day: client portals that surface project status from a Coda tracker, internal dashboards that show live operational data to teammates who don't have a Coda seat, and member-facing views powered by the tables your team already maintains in Coda.
## Available Actions
### List rows
Pull rows from a Coda table into a Softr list block, dashboard, or admin view — ideal for showing project status, inventory, or any tracked data to clients and teammates. Pick the doc and table, optionally filter to just the rows you need, and map the columns into your Softr app.
### Get row
Look up a single Coda row by its ID to display its details inside your Softr app or use its values later in the workflow.
### Create or update row
Add a new row to a Coda table from a form submission or workflow step — or, by setting key columns, update the matching row when one already exists so you never create duplicates.
### Update row
Change the column values of an existing Coda row when something happens in your Softr app, such as a status change or an approval.
### Delete row
Remove a row from a Coda table as part of a workflow — for example when a request is cancelled or a record is archived in your Softr app.
## Key Benefits
- **No-code data access:** Bring Coda tables into your Softr app visually — no scripts, no API calls to manage.
- **Always up to date:** Each workflow run fetches the latest rows, so your dashboards and portals reflect what's in Coda right now.
- **Client-friendly views:** Give customers a polished Softr portal backed by the Coda tables your team already maintains, without handing out Coda seats.
- **Targeted results:** Filter rows by column value so each view shows exactly the data that matters.
- **Built for the apps you ship:** Power member portals, admin tools, and dashboards from a single Coda source of truth.
## Example Use Cases
| Use Case | Description |
| :--------------------------- | :------------------------------------------------------------------------------------------------------------- |
| **Project status dashboard** | Surface live rows from a Coda project tracker inside a Softr list block so non-Coda users can follow progress. |
| **Client-facing portal** | Show each client only their rows from a shared Coda table, filtered by company or account. |
| **Internal operations view** | Pull inventory, orders, or requests from Coda into an admin dashboard your team can scan at a glance. |
| **Member directory** | Power a member portal from a Coda table of people, surfacing names, roles, and details in Softr. |
| **Scheduled data digest** | On a recurring workflow, fetch the latest rows from Coda to feed a report or summary view. |
## How to Connect Softr with Coda
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a Coda action.
3. Click **Connect to Coda** and paste your Coda API token. You can generate one in your Coda account settings at [coda.io/account](https://coda.io/account).
4. Pick the doc and table you want to work with.
5. Map the columns from your Coda table to your Softr list, records, or later workflow steps — and optionally add a filter to narrow the rows returned.
6. Save and activate your workflow.
---
# DocsAutomator integration
Source: https://docs.softr.io/workflows/integrations/docs-automator
Connect DocsAutomator with your Softr applications to turn form submissions, member sign-ups, and record updates into polished, branded PDFs — contracts, invoices, certificates, and reports — generated automatically from your own Google Docs templates.
## Overview
The Softr DocsAutomator integration lets you generate professional documents on demand from inside your no-code app. Design a template once in Google Docs, drop in `{placeholder}` tags wherever data should appear, and let Softr fill it in with values from form submissions, list records, or any earlier step in your workflow. The finished PDF is produced automatically — no manual copy-paste, no formatting drift.
This is the missing piece for any Softr app where users expect a real document at the end of a process: client portals that hand off signed agreements, booking tools that issue invoices, course platforms that award completion certificates, and internal tools that fire off branded reports straight from your data.
## Available Actions
### Create document
Generate a PDF from a Google Docs template by passing in the values that fill its placeholders — kicked off by a form submission, a button click, or any other workflow trigger.
## Key Benefits
- **No-code document automation:** Design templates visually in Google Docs and wire them into Softr workflows without writing a line of code.
- **Use the editor you already know:** Templates live in Google Docs, so anyone on your team can update wording, branding, or layout without touching your app.
- **Polished PDF output:** Every document comes out as a clean, share-ready PDF — consistent typography, logos, and structure on every run.
- **Personalized at scale:** Pull names, dates, line items, and any other dynamic data from your Softr records or forms straight into the document.
- **Member-facing or internal:** Deliver documents to your customers automatically, or generate them quietly in the background for your team.
## Example Use Cases
| Use Case | Description |
| :--------------------------------- | :---------------------------------------------------------------------------------------------------------------------- |
| **Contracts and agreements** | Generate a tailored contract PDF the moment a client submits a form, ready to send for signature. |
| **Invoices after a booking** | Fire off a branded invoice automatically when a member books a service or completes a checkout in your Softr app. |
| **Certificates of completion** | Issue personalized course-completion certificates to members the second they finish a program or pass a milestone. |
| **Custom client reports** | Let internal teams produce on-demand reports — pulled live from app data — straight from a button in a Softr dashboard. |
| **Branded sales proposals** | Turn a CRM-style internal tool into a one-click proposal generator, with deal data dropped into a polished template. |
| **Quotes and order confirmations** | Email a formatted quote or order confirmation as soon as a lead requests pricing or a customer places an order. |
## How to Connect Softr with DocsAutomator
1. In Google Docs, create the template you want to use and add `{placeholder}` tags wherever dynamic data should appear (for example `{client_name}`, `{invoice_total}`). In your DocsAutomator account, register the template and copy your API key from the account settings.
2. Open your Softr app and go to **Workflows**.
3. Create a new workflow and add the **Create document** DocsAutomator action.
4. Click **Connect to DocsAutomator** and paste your API key.
5. Pick the template you want to fill.
6. Map fields from your Softr forms, records, or earlier workflow steps to the template's placeholders, then save and activate your workflow.
---
# Documint integration
Source: https://docs.softr.io/workflows/integrations/documint
Connect Documint with your Softr applications to generate polished PDF documents — invoices, contracts, certificates, and more — directly from your workflows, with zero manual formatting.
## Overview
The Softr Documint integration lets you turn workflow data into finished documents automatically. Design your document once as a template in Documint, then generate a new PDF every time a workflow runs — populated with data from your app, no copy-pasting or manual document creation required.
Once you connect a template, Softr automatically reads its fields, so you always map data to the placeholders your template actually has — including repeating sections like line items, which can be bound to a list from earlier in your workflow.
## Available Actions
### Create document
Generate a document from a Documint template. Pick the template, map its fields to data from your workflow, and get back a link to the finished document — ready to send, store, or share.
## Key Benefits
- **No-code simplicity:** Configure document generation visually in Softr, without any technical setup.
- **Always in sync with your template:** Fields are read live from your chosen Documint template, so the mapping never drifts out of date when you update the template's design.
- **Repeating sections made easy:** Bind a list of records from your workflow (e.g. order line items) directly to a repeating section in your template.
- **Event-driven generation:** Automatically produce a document the moment a form is submitted, a record is created, or any other app event occurs.
## Example Use Cases
| Use Case | Description |
| :-------------------------------------- | :------------------------------------------------------------------------------------------------------------ |
| **Invoice generation** | Automatically generate an invoice PDF whenever a new order is created in your app. |
| **Contract creation** | Produce a filled-in contract or agreement the moment a deal or application is approved. |
| **Certificates and reports** | Generate a personalized certificate or report from workflow data, ready to email to the recipient. |
| **Order confirmations with line items** | Merge a list of purchased items into a single order confirmation document using a repeating template section. |
## How to Connect Softr with Documint
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a Documint action.
3. Click **Connect Documint** when prompted to configure the connection.
4. Paste your Documint API key. You can find it in your Documint account under **Account → API** (`https://app.documint.me/account/api`).
5. Choose the template to generate documents from — Softr loads its fields automatically — and map each field to data from your workflow.
6. Save your workflow and activate it.
---
# DocuSign integration
Source: https://docs.softr.io/workflows/integrations/docusign
Connect DocuSign with your Softr applications to automate your e-signature process end to end — send documents and templates for signature the moment something happens in your app, look up the status of an envelope on demand, cancel agreements that are no longer needed, and react instantly when a document is signed or declined. Build contract, onboarding, and approval workflows on top of live signature data, all without code.
## Overview
The Softr DocuSign integration lets you connect your no-code apps with your DocuSign account. Create envelopes from a document or a DocuSign template, send them for signature, void agreements, and fetch envelopes, recipients, and the data signers entered into form fields — all driven by the forms, sign-ups, and record actions you already build with in Softr. Every action returns the envelope or its details so you can use them in any downstream workflow step.
With Softr, you can turn a form submission into a signature request, send a contract automatically when a deal is marked won, surface the status of pending agreements in a member portal, and kick off follow-up automations the moment an envelope is completed or declined — keeping your app and your signing process in sync.
## Available Actions
### Create envelope
Create an envelope from a document you provide (via a file URL), add a signer and a signature field, and optionally send it for signature right away. Use it to turn a generated document or an uploaded file into a signature request without leaving Softr.
### Create envelope from template
Create and send an envelope from an existing DocuSign template — assign a recipient to a template role and pre-fill the template's merge fields with values from your app. Ideal for standardized contracts, NDAs, and agreements you send repeatedly.
### Send envelope
Send a draft (created-but-not-yet-sent) envelope to its recipients, for example after a review or approval step has passed in your workflow.
### Void envelope
Cancel an envelope with a reason, for instance when an agreement is superseded, a deal falls through, or the wrong document was sent.
### Get envelope
Fetch a single envelope by ID — including its recipients and documents — to read its status and details in a later workflow step or surface them inside Softr.
### List envelopes
Retrieve a page of envelopes filtered by date range, status, or search text — to show in a list block, sync to a Softr database, or loop over in a workflow.
### Get envelope recipients
Fetch the recipients of an envelope along with their signing status and routing order, so you can see who has signed and who is still pending.
### Get envelope form data
Fetch the data signers entered into an envelope's form fields, ready to save to a Softr database, route into another tool, or use in a follow-up step.
## Available Triggers
### Envelope event
Fires when an envelope or recipient reaches a key milestone in DocuSign. Choose which event to listen to — or react to all of them:
- **Envelope completed** — every recipient has signed and the envelope is complete.
- **Envelope declined** — a recipient declined to sign and the envelope is declined.
- **Recipient completed** — an individual recipient finished signing.
- **Recipient declined** — an individual recipient declined to sign.
The trigger hands you the envelope's details — status, subject, sender, recipients, documents, and key timestamps — so you can update records, notify your team, or start a follow-up workflow the moment the event happens.
## Key Benefits
- **No-code e-signatures:** Send documents for signature and react to signing events from your Softr app — no API setup, no scripts.
- **Two-way automation:** Push envelopes into DocuSign and react to completed or declined events coming back out, so your app and your agreements stay aligned.
- **Templates and merge fields:** Send standardized agreements from DocuSign templates with fields pre-filled from your Softr data.
- **Live signature status in your app:** Pull envelopes, recipients, and form data into list and detail blocks to build contract and onboarding dashboards.
- **End-to-end workflows:** Tie signing to the rest of your app — provision access, update records, send emails, and notify your team in the same workflow.
## Example Use Cases
| Use Case | Description |
| :---------------------------- | :-------------------------------------------------------------------------------------------------------------------------- |
| **Contract on deal won** | Send an agreement from a DocuSign template when a deal is marked won, with the client's details pre-filled. |
| **Form to signature request** | Turn a Softr form submission into an envelope and send it to the submitter for signature automatically. |
| **Onboarding paperwork** | Send NDAs or onboarding documents when a new member signs up, then unlock access once they're signed. |
| **Signing status portal** | Use **List envelopes** and **Get envelope recipients** to show members and admins which agreements are pending or complete. |
| **Auto-update on completion** | Trigger on **Envelope completed** to mark a record as signed, store the form data, and notify your team. |
| **Cancel stale agreements** | Void envelopes that are no longer valid from a Softr admin view when a deal falls through or terms change. |
## How to Connect Softr with DocuSign
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a DocuSign action (or the **Envelope event** trigger).
3. Click **Connect to DocuSign** and sign in with your DocuSign account, then review and authorize the requested permissions.
4. Pick the operation you need — create an envelope, send it, void it, list envelopes, and so on.
5. For template-based sends, choose the **template**, assign the **role**, and map your data to the template's merge fields.
6. Map fields from your Softr forms, records, or previous workflow steps to the action's inputs (such as signer email and name, document, or envelope ID).
7. Save and activate your workflow.
---
# Asana integration
Source: https://docs.softr.io/workflows/integrations/asana
Connect Asana with your Softr applications to turn form submissions, sign-ups, and record changes into real work — create tasks, keep projects up to date, and keep your team aligned without any manual data entry. Build workflows that push the right work into Asana the moment it happens in your app.
## Overview
The Softr Asana integration lets your app create and manage work in your Asana workspace directly from your workflows. Trigger tasks from form submissions, user sign-ups, button clicks, or record updates, add comments and subtasks to keep conversations in sync, and pull in users and projects to enrich what you build.
Whether you're building a client portal, an internal task tracker, or a project-status dashboard, Asana gives your Softr app a live connection to how your team actually delivers work — new requests become tasks, status changes flow back and forth, and everyone stays on the same page in real time.
## Available Actions
### Task: Create
Create a new Asana task whenever a workflow runs — set the name, description, assignee, due date, project, and more — so a form submission or sign-up becomes actionable work instantly.
### Task: Get
Pull a single task into your workflow to display it in a Softr list, log it to a record, or use its details in the next step.
### Task: Update
Change any field on an existing task — reassign it, move its due date, or mark it complete — automatically as records change in your app.
### Task: Delete
Remove a task that's no longer needed, keeping your Asana workspace tidy as work is cancelled or cleaned up.
### Task: List
Pull a list of tasks from a project, section, or assignee into your Softr app to power a live task board or project dashboard.
### Task: Search
Find tasks across a workspace by assignee, project, tag, or date range — perfect for surfacing overdue or high-priority work in a digest or dashboard.
### Subtask: Create
Break a task down into steps by adding subtasks automatically — ideal for spinning up a checklist when a new client or project kicks off.
### Subtask: List
Pull the subtasks of a task into your workflow to show progress or drive the next step.
### Comment: Add to Task
Post a comment on a task to keep everyone in the loop — log a status update, a customer note, or a hand-off message right where the work lives.
### Tag: Add to Task
Apply a tag to a task to categorize it by customer, priority, or stage as it moves through your workflow.
### Tag: Remove from Task
Take a tag off a task once it's resolved or moves to a new stage.
### Project: Create
Spin up a new project when a new client, campaign, or initiative starts, so work has a home from day one.
### Project: Get
Pull a project's details into your workflow to display or reference in later steps.
### Project: Update
Keep a project's name, dates, owner, or status in sync with what's happening in your Softr app.
### Project: Delete
Remove a project that's been cancelled or archived.
### Project: List
Pull the list of projects in a workspace to power a project picker or portfolio view inside your Softr app.
### User: Get
Look up a specific workspace member to assign work to the right person or personalize a task.
### User: List
Pull the members of a workspace into your Softr app to build assignee pickers or team directories.
## Key Benefits
- **No-code work automation:** Set up task creation, updates, comments, and clean-up visually inside Softr — no scripting or API keys required.
- **End-to-end task lifecycle:** Create, update, comment on, tag, and complete tasks driven by what your users do in your app.
- **Always-current options:** Workspaces, projects, users, tags, and teams load live from your connected account, so your dropdowns stay up to date.
- **Real-time team alignment:** New requests become Asana tasks the moment they arrive, and status changes stay in sync both ways.
- **Powerful search and filtering:** Surface tasks by assignee, project, tag, or due date to build focused dashboards and digests.
## Example Use Cases
| Use Case | Description |
| :------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------- |
| **Form-to-task intake** | A Softr form submission creates an Asana task with the request details and assigns it to the on-duty team member. |
| **Client onboarding checklist** | When a new client signs up, auto-create a task with a set of subtasks so nothing in the onboarding gets missed. |
| **Status sync** | When a record moves to "In progress" in your Softr database, update the linked Asana task and post a comment. |
| **Internal task portal** | Build a Softr page that lists open Asana tasks for a project, with a quick-update form so your team can act without leaving the app. |
| **Overdue-work digest** | Search for tasks due before today that aren't complete, and feed them into a daily email or Slack digest. |
| **New-project provisioning** | Spin up a new Asana project automatically whenever a new campaign or client is added in Softr. |
## How to Connect Softr with Asana
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add an Asana action — create a task, update a task, add a comment, create a project, and more.
3. Click **Connect to Asana** and complete the auth step — sign in with Asana to authorize Softr, or paste a personal access token from your Asana account settings.
4. Select the workspace the action should work in, then pick the project or task it applies to.
5. Map fields from your Softr forms, records, or previous workflow steps to the action's inputs.
6. Save and activate your workflow.
---
# Fathom integration
Source: https://docs.softr.io/workflows/integrations/fathom
Connect Fathom with your Softr applications to automate meeting follow-ups, route AI-generated meeting content into your tools, and keep your team aligned. Build workflows that react to newly processed Fathom meetings — all without code.
## Overview
The Softr Fathom integration lets you connect your no-code apps with Fathom, the AI meeting assistant that records, transcribes, and summarizes calls. List recent meetings, fetch summaries and transcripts on demand, and trigger workflows the moment Fathom finishes processing a recording.
With Softr, you can fan out meeting summaries to Slack or email, push action items into a CRM or project tool, archive transcripts to a database, and any other automation built on top of meeting outcomes.
## Available Actions
### List Meetings
Retrieve up to 30 most-recent Fathom meetings, with optional filters by created-date range, recorder email, team, and invitee email domain. You can opt-in to include the AI summary, transcript, action items, and CRM matches per meeting. Pagination across Fathom's cursor pages is handled internally.
### Get Recording Summary
Fetch the AI-generated summary (Markdown) for a single recording by its ID.
### Get Recording Transcript
Fetch the full speaker-tagged transcript for a single recording by its ID. Long meetings can produce large payloads.
## Available Triggers
### New Meeting Content Ready
Fires when Fathom finishes processing a meeting and its content (summary, transcript, action items, CRM matches) becomes available. You choose:
- **Recording scope** — which meetings should trigger this workflow (your recordings, recordings shared with you, team-shared recordings).
- **Content blocks** — which content fields to include in the trigger payload (summary, transcript, action items, CRM matches). At least one must be enabled.
The trigger payload mirrors the Meeting object returned by **List Meetings**, plus a `type` discriminator. Webhook deliveries are signed using the [Standard Webhooks](https://www.standardwebhooks.com/) scheme; Softr verifies the signature on every delivery.
## Key Benefits
- **No-code simplicity:** Configure Fathom actions and triggers visually in Softr, no API plumbing required.
- **End-to-end meeting automation:** From "meeting recorded" to "Slack message + CRM update + task created" — all in one workflow.
- **Selective payloads:** Only fetch what you need (summary, transcript, action items, CRM matches) to keep workflows fast.
- **Secure by default:** Standard Webhooks signature verification ensures only genuine Fathom deliveries trigger your workflow.
## Example Use Cases
| Use Case | Description |
| :------------------------------- | :--------------------------------------------------------------------------------------- |
| **Meeting summary to Slack** | Post the AI summary of every new meeting to a Slack channel. |
| **CRM update after sales calls** | Update HubSpot or Stripe records with action items and notes from sales calls. |
| **Action item tracking** | Create tasks in monday.com or ClickUp based on the action items extracted by Fathom. |
| **Transcript archive** | Save full transcripts to a Softr database or Notion page for searchable records. |
| **Follow-up email automation** | Send a recap email to invitees after every customer meeting. |
| **Meeting digest** | Aggregate the day's recordings into a single end-of-day summary using **List Meetings**. |
## How to Connect Softr with Fathom
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a Fathom action or trigger.
3. Click **Connect Fathom** and enter your Fathom API key.
4. To generate an API key, sign in to Fathom and navigate to **User Settings → API Access**. The key grants access to meetings recorded by you or shared to your team.
5. For triggers, choose the recording scope and content blocks you want to receive in the payload.
6. Configure inputs (date filters, recording ID, etc.) and save.
7. Activate your workflow — Softr will register the webhook with Fathom automatically when needed.
## Rate Limits
Fathom enforces a rate limit of **60 requests per 60-second rolling window** per user, shared across all of a user's API keys. Softr's Fathom client respects this limit and backs off automatically when throttled.
---
# Fillout integration
Source: https://docs.softr.io/workflows/integrations/fillout
Connect Fillout with your Softr applications to put your form submissions to work the moment they arrive. Start workflows from any Fillout form — then notify your team, create records, and route the answers wherever they need to go, all without code.
## Overview
The Softr Fillout integration lets you connect your no-code apps with Fillout, the form and survey builder. When a new submission is received on a form you choose, Softr starts a workflow and hands you the submitted answers, ready to map into any later step — databases, emails, CRMs, or AI actions.
With Softr, every Fillout response becomes the start of something: save it to a Softr database that powers a portal or dashboard, send a confirmation to the respondent, alert the right teammate, or kick off a review process — automatically.
## Available Triggers
### New Submission
Fires when a new submission is received on the Fillout form you select, with the submitted answers available to use in every later workflow step.
## Key Benefits
- **No-code form automation:** Pick a form and act on every submission visually in Softr — nothing to wire up by hand.
- **Instant reactions:** Workflows start the moment a form is submitted, so follow-ups never wait.
- **Route answers anywhere:** Map responses into Softr databases, emails, Slack messages, CRM records, or AI actions.
- **Keep your favorite form builder:** Keep collecting responses in Fillout while Softr handles what happens next.
## Example Use Cases
| Use Case | Description |
| :----------------------------- | :------------------------------------------------------------------------------------------------ |
| **Submissions to a database** | Save every Fillout response to a Softr database that powers a list, portal, or admin dashboard. |
| **Lead routing to CRM** | Create or update a contact in HubSpot, Salesforce, or Brevo when a lead form is submitted. |
| **Instant team notifications** | Post new submissions to a Slack channel or send an email so the right person responds fast. |
| **Application intake** | Kick off an onboarding or review workflow whenever an application or registration form comes in. |
| **AI-assisted triage** | Summarize and categorize each submission with an AI action, then branch the workflow by category. |
## How to Connect Softr with Fillout
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add the Fillout **New Submission** trigger.
3. Click **Connect Fillout** and sign in to your Fillout account to authorize Softr.
4. Pick the **form** you want to watch for new submissions.
5. Map the submission's answers to the inputs of your downstream actions — database records, emails, notifications, and more.
6. Save and activate your workflow.
---
# Gemini integration
Source: https://docs.softr.io/workflows/integrations/gemini
Connect Gemini with your Softr applications to use Google's AI models for writing, summarizing, categorizing, and image generation inside your workflows. Turn form submissions and records into polished content and visuals — no code required.
## Overview
The Softr Gemini integration sends text from your workflows to Google's Gemini models and returns the result for use in any later step. Draft copy, condense long submissions, sort records into categories, run any custom prompt, or generate images with Google's Nano Banana image model — then write the output to a database, an email, or the next action in the chain.
In a typical Softr app, Gemini reacts to what your users do: a client uploads a request through a form block, a member updates their profile, a new record lands in a table — and the workflow answers with generated text, a summary for your team, a routing label, or a brand-new image.
## Available Actions
### Custom prompt
Send your own prompt to Gemini — with data mapped in from forms, records, or earlier steps — and use the response anywhere in your workflow.
### Write
Generate original text such as email drafts, descriptions, announcements, or personalized messages.
### Summarize Text
Condense long text — briefs, feedback, meeting notes — into a short summary your team can scan.
### Categorize
Assign text to one of your predefined categories so submissions and records get routed automatically.
### Nano Banana 2 (image)
Generate an image from a text prompt with Google's Nano Banana image model and use it in your app — as a record attachment, listing visual, or email asset.
## Key Benefits
- **Google's AI, no code:** Use Gemini's text and image models from a visual workflow editor — no scripts or API plumbing.
- **Text and images together:** Write copy and generate matching visuals for records, listings, and emails in one workflow.
- **Your own Google AI account:** Connect with your API key and use your own models, quotas, and billing.
- **Routing-ready output:** Use Categorize to produce clean labels you can branch on, filter with, or store in a record.
## Example Use Cases
| Use Case | Description |
| :------------------------------ | :-------------------------------------------------------------------------------------------------------- |
| **Visuals for every listing** | When a member adds a product or event through your portal, generate an image and attach it to the record. |
| **Summarize incoming requests** | Condense long form submissions into short summaries your admin dashboard can display at a glance. |
| **Sort and route submissions** | Categorize new entries — support, sales, feedback — and branch the workflow to the right follow-up. |
| **Content on autopilot** | Draft descriptions, announcements, or member updates from record data whenever something changes. |
| **Personalized onboarding** | When a user signs up, write a tailored welcome message from their answers and send it automatically. |
## How to Connect Softr with Gemini
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a Gemini action.
3. Click **Connect Gemini** and paste your Gemini API key. You can create one for free in [Google AI Studio](https://aistudio.google.com) under **Get API key**.
4. Choose the model and write your instructions or prompt.
5. Map fields from your Softr forms, records, or previous workflow steps into the prompt inputs.
6. Save and activate your workflow.
---
# Gmail integration
Source: https://docs.softr.io/workflows/integrations/gmail
Connect Gmail with your Softr applications to send personalized emails, manage replies, and keep customer conversations organized — directly from your no-code app. Build workflows that turn form submissions, sign-ups, and record changes into the right email at the right time.
## Overview
The Softr Gmail integration lets your app send and manage email without leaving your workflows. Trigger emails from form submissions, user sign-ups, button clicks, or record updates, and let your team handle replies, drafts, and inbox organization from inside an admin dashboard or member portal.
Whether you're building a customer support portal, a client onboarding flow, or a CRM-lite tool for your sales team, Gmail gives your Softr app a fully connected inbox — outbound notifications, follow-up replies, and label-based organization, all driven by what your users do in Softr.
## Available Actions
### Send email
Send a personalized email from your Gmail account whenever a workflow runs — perfect for welcome messages, confirmations, and notifications.
### Send reply
Reply to an existing email thread automatically, keeping the full conversation history intact for your team and your customers.
### Create draft
Prepare an email and save it as a draft in Gmail so a team member can review and send it manually.
### Create draft reply
Draft a response to an existing thread and leave it ready in Gmail for a human touch before sending.
### Read email
Pull the contents of a specific email into your workflow to display it in a Softr list, log it to a record, or use it in the next step.
### Archive email
Clear processed messages out of the inbox automatically once your workflow has handled them.
### Delete emails
Permanently remove emails that no longer need to be kept around — useful for cleaning up automated noise or processed notifications.
### Add label to email
Tag an email with one or more Gmail labels to keep your inbox neatly categorized by customer, status, or priority.
### Remove label from email
Take a label off an email once a thread is resolved or moves to a new stage.
### Create label
Spin up a new Gmail label on the fly so your workflows can organize messages into the exact buckets your team needs.
## Key Benefits
- **No-code email automation:** Set up email sending, drafting, and inbox cleanup visually inside Softr — no API keys or scripting required.
- **Personalized at scale:** Pull names, order details, or any record field straight into the email body so every message feels written for one person.
- **Keep your team in control:** Use drafts when a human review is needed and auto-send for routine confirmations — choose the right level of automation per workflow.
- **Organized inbox by default:** Apply, remove, and create labels automatically so customer threads stay sorted without manual triage.
- **Faster customer response:** React to form submissions and sign-ups the moment they happen, instead of letting messages pile up.
## Example Use Cases
| Use Case | Description |
| :------------------------------- | :------------------------------------------------------------------------------------------------------------------- |
| **Welcome emails on sign-up** | Send a personalized welcome email the moment a new member signs up to your Softr app. |
| **Form-submission auto-replies** | Automatically reply to form submissions to confirm receipt and set expectations on next steps. |
| **Support portal replies** | Let your support team respond to customer threads from inside a Softr admin dashboard, with full thread context. |
| **Client onboarding sequences** | Trigger a series of onboarding emails as new clients move through stages in your Softr CRM. |
| **Inbox triage and labeling** | Automatically label incoming emails by customer, project, or priority so your team always knows what to handle next. |
| **Follow-up drafts for review** | Prepare draft replies for sales reps to review and send, combining automation with a personal touch. |
## How to Connect Softr with Gmail
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a Gmail action — send, reply, draft, label, archive, or delete.
3. Click **Connect Gmail** and sign in with your Google account to authorize Softr.
4. Map fields from your Softr forms, records, or previous workflow steps into the email's recipient, subject, body, and labels.
5. Choose triggers — form submissions, user sign-ups, record updates, or scheduled runs — to decide when the workflow runs.
6. Save and activate your workflow.
---
# GoHighLevel integration
Source: https://docs.softr.io/workflows/integrations/gohighlevel
Connect GoHighLevel with your Softr applications to keep your CRM in step with your app — capture leads from forms, move deals through your pipelines, assign follow-up tasks, and book appointments, all without code. Workflows can also start the moment a contact is created or an opportunity changes stage in GoHighLevel.
## Overview
The Softr GoHighLevel integration moves data both ways. From your Softr app into GoHighLevel: when a form is submitted, a user signs up, or a record changes, your workflow can create or update contacts, create and update opportunities, manage a contact's tasks, and book appointments on a calendar. From GoHighLevel back into Softr: instant triggers start your workflows when a contact is created or an opportunity moves to another stage.
Each connection is linked to one GoHighLevel business account (sub-account). Softr picks up that account's pipelines, stages, calendars, users, and custom fields, so the fields you see in the workflow builder match your CRM.
## Available Actions
### Contacts
#### Create or update contact
Create a contact, or update the existing one when a contact with the same email address or phone number already exists — no duplicate checks needed. Set the contact's name, company, address, website, source, timezone, tags, assigned user, custom fields, and whether they should receive messages (**Do not disturb**).
Setting **Tags** replaces all of the contact's current tags.
#### Update contact
Update an existing contact by its ID. Only the fields you fill in are changed; the rest stay as they are.
#### Get contact
Retrieve a contact by its ID and use its details in later steps — for example, the full details of the contact that started the workflow.
#### Search contacts
Search contacts by name, phone, email, tags, or company. Leave the search query empty to list all contacts. Results come in pages of up to 100 contacts, sorted by date added or date updated.
#### Delete contact
Delete a contact by its ID.
### Opportunities
#### Create opportunity
Create an opportunity in a pipeline stage for a contact, with its name, status, value, assigned user, expected close date, win probability, and custom fields.
#### Update opportunity
Update an opportunity by its ID — move it to another stage, change its status, value, or assigned user. The new stage must belong to the opportunity's pipeline. When you set the status to lost, you can also give a lost reason.
#### Get opportunity
Retrieve an opportunity by its ID.
#### Search opportunities
Search opportunities, optionally filtered by pipeline, stage, status, assigned user, and creation date. Results come in pages of up to 100 opportunities.
### Tasks
#### Create task
Create a task for a contact, with a title, description, due date, and assigned user.
#### Update task
Update a contact's task — change its title, description, due date, or assigned user, or mark it as completed or not completed.
#### List tasks
List all tasks of a contact.
#### Delete task
Delete a task from a contact.
### Calendars
#### Book appointment
Book an appointment on a GoHighLevel calendar for a contact. Set the start time, and optionally the end time, title, description, status, assigned user, and meeting location (Zoom, Google Meet, Microsoft Teams, phone, address, or a custom location).
- If you leave the end time empty, the calendar's slot duration is used.
- If you leave the meeting location empty, the calendar's default location is used.
- By default, the booking follows the calendar's availability and scheduling rules. Turn on **Skip free-slot validation** to book a slot that is already taken, or **Ignore date range** to book outside the calendar's scheduling window.
- Turn on **Send notifications** to run the calendar's automations and send its notifications for this booking.
## Available Triggers
### Contact created
Starts a workflow when a new contact is created in GoHighLevel.
### Opportunity stage changed
Starts a workflow when an opportunity moves to a different stage in GoHighLevel.
To test a trigger, create a contact or move an opportunity to another stage in GoHighLevel, then load the event in the workflow builder.
## Key Benefits
- **No-code CRM automation:** Keep GoHighLevel contacts, opportunities, and tasks up to date from your Softr app — no scripts or developer help required.
- **No duplicate contacts:** Create or update contacts by email address or phone number.
- **Pipelines that move themselves:** Create opportunities and move them between stages as things happen in your app.
- **Real-time triggers:** React instantly when a contact is created or an opportunity changes stage in GoHighLevel.
- **Matches your account:** Pipelines, stages, calendars, users, and custom fields are loaded from your GoHighLevel business account.
## Example Use Cases
| Use Case | Description |
| :---------------------- | :--------------------------------------------------------------------------------------------------------- |
| **Lead capture** | Create or update a GoHighLevel contact whenever someone submits a form in your Softr app. |
| **Deal tracking** | Create an opportunity in your sales pipeline when a member requests a quote, and move it when they accept. |
| **Follow-up tasks** | Create a task for your team when a client submits a request in your client portal. |
| **Appointment booking** | Book a GoHighLevel appointment from a booking form in your Softr app. |
| **Client onboarding** | When an opportunity moves to "Won", create the client's records and give them access to your Softr portal. |
| **CRM to app sync** | When a contact is created in GoHighLevel, add them to a Softr table. |
## How to Connect Softr with GoHighLevel
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a GoHighLevel action or trigger, for example **Create or update contact**.
3. Click **Connect to GoHighLevel** and sign in to your GoHighLevel account.
4. Choose the business account (sub-account) to connect, and approve the requested permissions. If you sign in with an agency account, choose one of its sub-accounts.
5. Choose the trigger that should run the workflow (form submission, sign-up, record update, schedule).
6. Fill in the action's settings — using fields from your Softr forms, records, or previous workflow steps.
7. Save and activate your workflow.
To connect several business accounts, add a connection for each one.
To remove Softr's access, delete the connection in Softr. This also uninstalls the Softr app from that GoHighLevel business account, so any other Softr connections to the same business account stop working too.
---
# Google Calendar integration
Source: https://docs.softr.io/workflows/integrations/google-calendar
Connect Google Calendar with your Softr applications to turn form submissions and member actions into real calendar events. Build booking portals, internal scheduling tools, and event workflows that keep everyone's calendar up to date — without code.
## Overview
The Softr Google Calendar integration lets your no-code app create and manage events in any Google Calendar your team uses. Trigger event creation from form submissions, member sign-ups, button clicks, or status changes, and let your workflows handle the scheduling, invitations, and follow-up automatically.
Whether you're running a coaching portal where clients self-book sessions, an internal tool that schedules onboarding calls for new hires, or a member community that organizes events, Google Calendar gives your Softr app a real scheduling backbone — complete with attendee invites and calendar reminders.
## Available Actions
### Create detailed event
Create a fully configured calendar event — title, description, start and end times, location, and calendar — directly from a Softr workflow.
### Add attendees to event
Invite one or more guests to an existing calendar event so they receive the meeting invitation and stay in sync with any updates.
## Key Benefits
- **No-code scheduling:** Wire up calendar workflows visually in Softr — no scripts, no APIs, no developer required.
- **Real-time event creation:** Turn every form submission, sign-up, or record update into a scheduled event the moment it happens.
- **Centralized team coordination:** Keep client meetings, internal sessions, and member events on the same Google Calendars your team already lives in.
- **Automated invitations:** Add attendees automatically so guests get the invite — and the reminders — without anyone copy-pasting emails.
- **Member-facing or internal:** Power customer-facing booking portals or back-office scheduling tools from the same building blocks.
## Example Use Cases
| Use Case | Description |
| :----------------------------------- | :------------------------------------------------------------------------------------------------------------- |
| **Client booking portal** | Let clients pick a time in a Softr form and automatically create the session in your team's Google Calendar. |
| **New member onboarding calls** | Schedule an onboarding call on the success team's calendar whenever a new user signs up to your Softr app. |
| **Coaching and consulting sessions** | Turn paid bookings on a member portal into confirmed calendar events with the coach and client invited. |
| **Internal interview scheduling** | Create interview slots and add the hiring panel as attendees when a candidate moves to the next stage. |
| **Community events and webinars** | Spin up a calendar event for every approved event submission and invite the organizers and speakers as guests. |
| **Service appointments** | Convert appointment requests submitted in your Softr app into events on the assigned team member's calendar. |
## How to Connect Softr with Google Calendar
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a Google Calendar action.
3. Click **Connect to Google Calendar** and sign in with the Google account whose calendar you want to use.
4. Approve access so Softr can create events and manage attendees on your behalf.
5. Pick the calendar you want events to land in.
6. Map fields from your Softr forms, records, or previous workflow steps to the event details — title, description, start and end times, and attendees.
7. Save and activate your workflow.
---
# Google Sheets integration
Source: https://docs.softr.io/workflows/integrations/google-sheets
Connect Google Sheets with your Softr applications to turn any spreadsheet into a live backend for your no-code app. Capture form submissions, sync member data, build internal dashboards, and keep an audit trail of user activity — all without leaving Softr.
## Overview
The Softr Google Sheets integration lets your app read from and write to any Google Sheet you own or have access to. Add new rows when users submit forms, look up records to display in member dashboards, update data when statuses change, and clean up stale entries automatically — every change happens in real time as people use your Softr app.
Google Sheets fits naturally into Softr workflows wherever you'd otherwise need a database: lightweight CRMs, signup logs, internal request trackers, exportable reports, and member-facing portals backed by a sheet your team already maintains.
## Available Actions
### Add row
Append a new row to a Google Sheet whenever a user submits a form, signs up, or triggers a workflow in your Softr app.
### Get row
Look up a single row by a matching value to display its data in a Softr block or use it in the next workflow step.
### Get rows
Retrieve multiple rows from a sheet — filtered or in full — to power lists, dashboards, and reports inside your app.
### Update row
Find a row by a matching value and update its fields when a record changes, a status moves forward, or a member edits their profile.
### Update rows
Apply the same update across multiple matching rows in one step, ideal for bulk status changes or batch corrections.
### Delete row
Remove a single row from a sheet when a user cancels, a request is resolved, or stale data needs to go.
### Delete rows
Clear out multiple matching rows at once to keep your sheet tidy after bulk actions or scheduled clean-ups.
## Key Benefits
- **No-code simplicity:** Use any spreadsheet as a backend for your Softr app with a few clicks — no databases, no SQL, no setup.
- **Real-time sync:** Every form submission, profile update, or record change in Softr is reflected in your sheet instantly.
- **Familiar to your team:** Keep working in the tool your team already knows while powering rich, dynamic Softr apps on top of it.
- **Read and write in both directions:** Push data into sheets and pull it back into Softr lists, profile blocks, or dashboards.
- **Bulk-friendly:** Update or clean up many rows at once to keep large datasets manageable without manual work.
## Example Use Cases
| Use Case | Description |
| :---------------------------------- | :----------------------------------------------------------------------------------------------------------------------- |
| **Form submissions to a sheet** | Capture every Softr form entry — leads, applications, support requests — as a new row in Google Sheets. |
| **Member portal backed by a sheet** | Power a members-only directory, course catalog, or resource hub with data your team manages in a spreadsheet. |
| **Internal dashboards** | Pull rows from an operations sheet into a Softr admin dashboard so your team can review and act on the latest data. |
| **Status updates and edits** | When a user changes a record in Softr, update the matching row in your sheet to keep both in sync. |
| **Audit trail of user actions** | Log every key action — sign-ups, purchases, approvals — to a Google Sheet for reporting and compliance. |
| **Exports and weekly reports** | Build scheduled workflows that gather data from your app and write clean reports to a shared sheet your team can review. |
## How to Connect Softr with Google Sheets
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a Google Sheets action.
3. Click **Connect to Google Sheets** and sign in with your Google account.
4. Authorize Softr to access the sheets you want to use in your workflows.
5. Pick the spreadsheet and worksheet you want to read from or write to.
6. Map fields from your Softr forms, records, or previous workflow steps to the columns in your sheet.
7. Save and activate your workflow.
---
# Granola integration
Source: https://docs.softr.io/workflows/integrations/granola
Connect Granola with your Softr applications to automate meeting workflows, access AI-powered meeting summaries, and keep your team aligned. Build workflows that react to new or updated meeting notes — all without code.
## Overview
The Softr Granola integration allows you to connect your no-code apps with your Granola meeting notes. Automatically retrieve meeting summaries, attendee lists, and calendar event details whenever a new meeting is recorded or an existing note is updated. Keep your team informed and your records up to date without manual effort.
With Softr, you can list and retrieve meeting notes, access AI-generated summaries, and trigger workflows when new meetings are captured or notes are modified in Granola.
## Available Actions
### List Notes
Retrieve a paginated list of meeting notes with optional date filters. Only notes with completed AI summaries are returned. Supports cursor-based pagination for large result sets.
### Get Note
Retrieve full details of a single meeting note, including the AI-generated summary, attendees, calendar event metadata, folder memberships, and optionally the full transcript.
## Available Triggers
### Note Created
Fires whenever a new meeting note with a completed AI summary appears in Granola. Use this to send notifications, update records, or trigger follow-up workflows.
### Note Updated
Fires when an existing meeting note is updated (summary regeneration, title edits, folder changes, etc.). Use this to keep downstream records in sync.
## Key Benefits
- **No-code simplicity:** Set up and manage your Granola workflows visually in Softr, without any technical setup.
- **AI-powered summaries:** Access Granola's AI-generated meeting summaries directly in your workflows.
- **Event-driven automation:** React to new or updated meeting notes with custom workflows.
- **Team alignment:** Automatically share meeting outcomes, action items, and attendee details with your team.
## Example Use Cases
| Use Case | Description |
| :----------------------------- | :-------------------------------------------------------------------------------------- |
| **Meeting summary to Slack** | Automatically post a meeting summary to a Slack channel when a new note is created. |
| **CRM update after meetings** | Update a CRM record with meeting notes and attendees when a note is created or updated. |
| **Action item tracking** | Create tasks in your project management tool based on meeting summaries. |
| **Meeting log database** | Automatically add new meeting notes to a Softr database for searchable records. |
| **Follow-up email automation** | Send follow-up emails to meeting attendees after a note is created. |
## How to Connect Softr with Granola
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a Granola action or trigger.
3. Click **Connect Granola** and enter your Granola API key.
4. Your API key can be found in your Granola workspace settings (Business or Enterprise plan required). Keys are prefixed with `grn_`.
5. Configure your inputs (date filters, note ID, etc.) and save.
6. Activate your workflow.
---
# HubSpot integration
Source: https://docs.softr.io/workflows/integrations/hubspot
Connect HubSpot with your Softr applications to keep your CRM in sync with everything happening inside your no-code app. Capture leads from forms, sync member sign-ups to Contacts, push deals from your sales tools, build member dashboards backed by live HubSpot data, and start workflows when a record is created or updated in HubSpot — all without writing a line of code.
## Overview
The Softr HubSpot integration links your Softr app directly to your HubSpot account so customer data flows both ways. Whenever someone signs up, fills out a form, updates a record, or takes an action in your app, you can create or update Contacts, Companies, Deals, or Tickets in HubSpot automatically — and pull HubSpot records back into Softr lists and detail pages just as easily. It also works the other way round: the **Record created** and **Record updated** triggers start a workflow when something changes in HubSpot, so your app, your team's Slack channel, or your Softr database can follow the CRM.
This makes HubSpot a natural fit for Softr customer portals, lead capture sites, internal sales tools, and member dashboards. Use it to turn your Softr forms into a CRM intake funnel, give your sales team a self-serve dashboard of HubSpot deals, or let members see and update their own CRM record from inside your app.
## Available Actions
### Add record
Create a HubSpot record (Contact, Company, Deal, Ticket, or any custom object) from a Softr form submission, sign-up, or workflow step.
### Get record
Look up a single HubSpot record by ID and pull its fields into your Softr app — perfect for showing a member their own profile or surfacing a deal on a detail page.
### Get records
Fetch a list of HubSpot records with optional filters and sorting, ready to display in a Softr list block, table, or kanban.
### Update record
Update the fields on a HubSpot record when something changes in Softr — a form edit, a status change, or a member updating their own profile.
### Update records
Update multiple HubSpot records in one workflow step — useful for bulk status changes, segment tagging, or syncing edits made across a Softr table.
### Delete record
Remove a HubSpot record when it's no longer needed — for example, cleaning up a lead a member has dismissed or a duplicate flagged in your admin tool.
### Delete records
Delete multiple HubSpot records at once, ideal for bulk clean-up workflows triggered from your Softr admin dashboard.
## Available Triggers
HubSpot triggers use background polling: Softr checks HubSpot for changes at a regular interval, so a workflow starts shortly after the change rather than the moment it happens. The interval depends on your plan (every minute on Professional plans and above) and is shown on the trigger in the workflow builder. Each trigger watches one object — Contacts, Companies, Deals, Tickets, or any other object the integration supports, including your custom objects.
### Record created
Starts a workflow when a new record is created in the selected HubSpot object — a new Contact from a HubSpot form, a Deal your sales team opened, a Ticket logged by support. Run a test on the trigger to pull a recent record and see the properties available to later steps.
### Record updated
Starts a workflow when a record in the selected HubSpot object is edited — a deal stage moves, a contact's lifecycle stage changes, a ticket is closed. Add a [Filter](/workflows/advanced-concepts#filter) step after the trigger to act only on the changes you care about.
## Key Benefits
- **No-code CRM automation:** Wire your Softr forms, sign-ups, and record actions to HubSpot visually — no developers, no Zapier zaps to maintain.
- **Two-way data flow:** Push new records into HubSpot and pull existing ones back into Softr lists and detail pages, all from the same workflow builder.
- **Built for customer portals:** Give members a branded Softr experience while your team continues to work in HubSpot — both sides stay in sync.
- **Works across every HubSpot object:** Contacts, Companies, Deals, Tickets, Notes, Tasks, Leads, Projects, Products, Line Items, Invoices, Subscriptions, Listings, Appointments, and your custom objects are all supported with the same simple actions.
- **Bulk operations included:** Update or delete many records in a single step when you need to act on a whole segment at once.
- **React to CRM changes:** Start a workflow when a record is created or updated in HubSpot, so the rest of your stack keeps up without anyone copying data by hand.
## Example Use Cases
| Use Case | Description |
| :----------------------------- | :------------------------------------------------------------------------------------------------------------------- |
| **Lead capture forms** | Turn Softr form submissions into new HubSpot Contacts and Deals, complete with source attribution and custom fields. |
| **Member sign-up sync** | When a new user signs up to your Softr portal, automatically create a matching Contact in HubSpot. |
| **Self-serve customer portal** | Let members view and update their own HubSpot Contact record from inside a Softr app. |
| **Internal sales dashboard** | Build a Softr admin tool that lists open Deals from HubSpot, with one-click updates back to the CRM. |
| **Support ticket intake** | Convert Softr support form submissions into HubSpot Tickets and route them to the right pipeline. |
| **Bulk segment management** | Update or delete groups of Contacts at once from a Softr admin view — perfect for list cleanup or bulk re-tagging. |
| **New lead alerts** | When a Contact or Deal is created in HubSpot, notify your team in Slack or add the record to your Softr database. |
| **Act on a stage change** | When a Deal is updated in HubSpot, check its stage and start the hand-off or onboarding workflow when it moves. |
## How to Connect Softr with HubSpot
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a HubSpot trigger, such as Record created, or a HubSpot action, such as Add record.
3. Click **Connect to HubSpot** and sign in to authorize Softr to access your HubSpot account.
4. Pick the HubSpot account or portal you want to connect if you manage more than one.
5. Choose the object you want to work with — Contact, Company, Deal, Ticket, or a custom object.
6. For an action, map fields from your Softr forms, records, or earlier workflow steps to the matching HubSpot properties. For a trigger, run a test to pull a sample record.
7. Save and activate your workflow.
---
# Jira integration
Source: https://docs.softr.io/workflows/integrations/jira
Connect Jira with your Softr applications to turn app activity into tracked work. Build workflows that open Jira issues automatically — from form submissions, new sign-ups, or record changes — so nothing your team needs to act on gets lost.
## Overview
The Softr Jira integration links your no-code apps directly to your Jira Cloud site. Whenever something happens in Softr — a customer submits a bug report, a record is flagged, a new request comes in — you can automatically create a Jira issue in the right project, with the right type, assignee, priority, and details filled in from your workflow.
Whether you're building a client portal, an internal operations tool, or a support dashboard, the Jira integration closes the gap between what happens in your Softr app and the work your team tracks in Jira.
## Available Actions
### Create issue
Open a new issue in a Jira project with a summary, description, issue type, assignee, priority, labels, and due date — all set dynamically from your Softr workflow. Project, issue type, assignee, and priority are chosen from live dropdowns pulled straight from your connected Jira site.
### Get issue
Retrieve the full details of a specific issue by its key — summary, status, assignee, priority, and timestamps — so you can use live Jira data in later workflow steps.
### Update issue
Change an existing issue's summary, description, assignee, priority, labels, or due date to keep Jira in sync with what's happening in your Softr app.
### Delete issue
Remove an issue from Jira by its key — with the option to delete its subtasks too — for cleanup or voided-request workflows.
### Search issues
Find issues with a JQL query and return the matching set, so you can power lists, dashboards, reports, or conditional logic inside your Softr app.
### Add comment
Post a comment to an issue — ideal for logging Softr form responses, status updates, or context straight onto the relevant Jira issue.
### List comments
Retrieve the comments on an issue to display an activity feed, drive follow-ups, or surface the latest discussion inside your Softr app.
## Key Benefits
- **No-code simplicity:** Configure every Jira action visually in Softr — no code required beyond the one-time API token setup.
- **Instant issue creation:** Turn any Softr form submission or record event into a Jira issue the moment it happens.
- **Always-current options:** Projects, issue types, assignees, and priorities load directly from your Jira account, so you never hardcode IDs.
- **Right work, right place:** Route each issue to the correct project and assignee automatically, based on your Softr data.
- **Ops-ready portals:** Build intake forms and internal tools in Softr that feed work straight into Jira, where your team already plans and ships.
## Example Use Cases
| Use Case | Description |
| :--------------------------- | :-------------------------------------------------------------------------------------------------------------------- |
| **Bug report intake** | Create a Jira issue automatically when a user submits a bug report form in your Softr portal. |
| **Feature request tracking** | Turn feature-request form submissions into Jira stories in your product backlog, tagged and assigned. |
| **Escalation from records** | When a record is flagged as high priority in your Softr database, open an urgent Jira issue for the responsible team. |
| **New client onboarding** | Auto-create an onboarding issue in Jira when a new member signs up to your Softr app. |
| **Internal request desk** | Let employees file IT or ops requests through a Softr form that creates a Jira issue in the right project. |
## How to Connect Softr with Jira
1. Open your Softr workspace and go to **Workflows**.
2. Create a new workflow or open an existing one, then add a Jira action.
3. In the **Account** field, click **Add another account** and enter your Jira **domain** (e.g. `https://your-team.atlassian.net`), your **email address**, and an **API token**.
4. To generate an API token, log into [id.atlassian.com](https://id.atlassian.com), go to **Security → API tokens**, and click **Create API token**.
5. Click **Save** — Softr verifies your credentials and connects the account.
6. Pick the **project** and **issue type**, map the remaining fields from your Softr forms or previous workflow steps, then activate your workflow.
---
# Jotform integration
Source: https://docs.softr.io/workflows/integrations/jotform
Connect Jotform with your Softr applications to put your form submissions to work automatically. Build workflows that fire the moment someone submits one of your Jotform forms — then notify your team, create records, and sync the answers wherever they need to go, all without code.
## Overview
The Softr Jotform integration lets you connect your no-code apps with Jotform, the online form builder. When a new submission is received on a form you choose, Softr starts a workflow and hands you the submitted answers — already mapped to human-readable question labels — so you can route the data into the rest of your app and tools.
With Softr, you can turn every Jotform submission into action: save it to a Softr database, send a confirmation email, post a Slack message, create a CRM contact, or kick off any other workflow built on top of the response.
## Available Triggers
### New Submission
Fires when a new submission is received on the Jotform form you select. The trigger payload includes the submission ID, form ID, submitter IP, creation time, and an `answers` object keyed by your form's question labels — including multi-part fields like full name and address, and uploaded file URLs. Softr resolves the field labels and types for the form you pick, so you can reference each answer directly in later workflow steps.
## Key Benefits
- **No-code form automation:** Connect a Jotform form and act on every submission visually in Softr — no webhooks to wire up by hand.
- **Readable answers:** Submitted data arrives keyed by your actual question labels, not cryptic field IDs, so mapping is effortless.
- **Instant reactions:** Workflows fire the moment a form is submitted — no polling, no delay.
- **Works with any form:** Pick any form on your Jotform account, including multi-part fields, file uploads, and multi-select questions.
## Example Use Cases
| Use Case | Description |
| :----------------------------- | :----------------------------------------------------------------------------------------------- |
| **Submissions to a database** | Save every Jotform response to a Softr database to power a list, portal, or admin dashboard. |
| **Lead routing to CRM** | Create or update a contact in HubSpot, Salesforce, or Xero when a lead form is submitted. |
| **Instant team notifications** | Post new submissions to a Slack channel or send an email so the right person responds fast. |
| **Application intake** | Kick off an onboarding or review workflow whenever an application or registration form comes in. |
| **File collection** | Capture uploaded files from a submission and archive their URLs to a database or storage tool. |
| **Confirmation follow-ups** | Send a personalized confirmation email to the submitter using the answers from their submission. |
## How to Connect Softr with Jotform
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add the Jotform **New Submission** trigger.
3. Click **Connect Jotform** and paste your Jotform API key. To generate one, sign in to Jotform and go to **Settings → API**, then create a new API key. Select your account region (US/global, EU, or HIPAA) if prompted.
4. Pick the **form** you want to watch for new submissions.
5. Map the submission's answers to the inputs of your downstream actions (database records, emails, Slack messages, and more).
6. Save and activate your workflow — Softr registers the webhook with Jotform automatically.
---
# Linear integration
Source: https://docs.softr.io/workflows/integrations/linear
Connect Linear with your Softr applications to turn app activity into tracked work. Build workflows that create Linear issues automatically — from form submissions, new sign-ups, or record changes — so every request lands in the team's queue without anyone copying it over by hand.
## Overview
The Softr Linear integration links your no-code apps directly to your Linear workspace. Whenever something happens in Softr — a customer reports a bug, a record gets flagged, a new request comes in — you can automatically create a Linear issue in the right team, with the title, description, assignee, priority, status, labels, project, and due date filled in from your workflow.
Whether you're building a client portal, an internal operations tool, or a support dashboard, the Linear integration closes the gap between what happens in your Softr app and the work your team plans and ships in Linear.
## Available Actions
### Create issue
Create a new issue in a Linear team with a title, description, assignee, priority, status, labels, project, and due date — all set dynamically from your Softr workflow. Teams, assignees, statuses, labels, and projects are chosen from live dropdowns pulled straight from your connected Linear workspace.
### Get issue
Fetch the full details of any Linear issue by its ID or identifier (like `ENG-123`) — title, status, assignee, priority, labels, and dates — and use them in the next steps of your workflow.
### Update issue
Change any field of an existing issue: retitle it, reassign it, move it to another status, team, or project, adjust its priority or labels, or set a new due date. Only the fields you fill in are changed.
### Delete issue
Move an issue to Linear's trash when it's no longer needed — for example when the related record is removed from your Softr app. Trashed issues stay recoverable in Linear for a grace period.
### List issues
Fetch a batch of issues — from a specific team or your whole workspace — and use them in later steps, for example to build digests or sync summaries into your Softr database.
### Create comment
Post a comment on any issue, with full Markdown support and optional threaded replies — perfect for pushing customer responses or status notes from your Softr app into the team's discussion.
### Add link to issue
Attach any URL to an issue — the Softr record it came from, a document, or a customer conversation — so the team has the full context one click away.
## Available Triggers
### On issue event
Start a workflow the moment an issue is created, updated, or deleted in a Linear team of your choice. Use it to sync issue changes back into your Softr database, notify stakeholders, or update customer-facing status pages in real time. You can listen to all issue events or only the ones you pick.
## Key Benefits
- **No-code simplicity:** Configure every Linear action visually in Softr — no code required beyond the one-time API key setup.
- **Instant issue creation:** Turn any Softr form submission or record event into a Linear issue the moment it happens.
- **Always-current options:** Teams, assignees, statuses, labels, and projects load directly from your Linear workspace, so you never hardcode IDs.
- **Right work, right team:** Route each issue to the correct team, project, and assignee automatically, based on your Softr data.
- **Ops-ready portals:** Build intake forms and internal tools in Softr that feed work straight into Linear, where your product team already plans its cycles.
## Example Use Cases
| Use Case | Description |
| :--------------------------- | :--------------------------------------------------------------------------------------------------------------------- |
| **Bug report intake** | Create a Linear issue automatically when a user submits a bug report form in your Softr portal. |
| **Feature request tracking** | Turn feature-request form submissions into labeled, prioritized issues in your product team's backlog. |
| **Escalation from records** | When a record is flagged as urgent in your Softr database, open a high-priority Linear issue for the responsible team. |
| **New client onboarding** | Auto-create an onboarding issue in Linear when a new member signs up to your Softr app. |
| **Internal request desk** | Let employees file IT or ops requests through a Softr form that creates a Linear issue in the right team. |
| **Feedback triage board** | Collect customer feedback in a Softr form and turn each entry into a Linear issue with the right label and project. |
## How to Connect Softr with Linear
1. Open your Softr workspace and go to **Workflows**.
2. Create a new workflow or open an existing one, then add a Linear action.
3. In the **Account** field, click **Add another account** and paste your Linear **personal API key**.
4. To create an API key, open Linear and go to **Settings → Security & access → Personal API keys**, then click **New API key**.
5. Click **Save** — Softr verifies your key and connects the account.
6. Pick the **team** for the issue, map the remaining fields from your Softr forms or previous workflow steps, then activate your workflow.
---
# Linkup integration
Source: https://docs.softr.io/workflows/integrations/linkup
Connect Linkup with your Softr applications to add grounded, real-time web search and page fetching to your workflows. Use Linkup to feed up-to-date context into AI prompts, power research automations, or extract content from any webpage on demand.
## Overview
The Softr Linkup integration allows you to call Linkup's web search and page fetch APIs directly from your workflows. Ask a natural-language question and get a synthesized answer with citations, or fetch a single URL and receive clean markdown that's ready to plug into an AI prompt or a database record.
With Softr, you can search the web, retrieve page content, and combine the results with any other action — send to Slack, store in a tablespace, or enrich a CRM record — all without code.
## Available Actions
### Search the web
Runs a natural-language web search and returns a synthesized answer backed by a list of sources. Supports standard (1 credit) and deep (10 credits) search modes, domain include/exclude filters, and publication-date filters.
### Fetch page
Fetches a single URL and returns a cleaned markdown representation of the page. Optionally extracts images and includes the raw HTML. Supports JavaScript rendering for SPAs and client-rendered pages.
## Key Benefits
- **Grounded AI context:** Give your AI actions up-to-date, source-cited information instead of relying on model training data.
- **No-code simplicity:** Configure searches and fetches visually in Softr — no external scripts or scraping setup.
- **Credit-metered:** Pay only for what you use; choose standard or deep search per call based on the precision you need.
- **Composable:** Pipe Linkup results straight into AI prompts, databases, Slack messages, or any other workflow action.
## Example Use Cases
| Use Case | Description |
| :------------------------ | :--------------------------------------------------------------------------------------------------- |
| **Research briefs** | Search the web on a topic and post a sourced summary to Slack every morning. |
| **Real-time AI answers** | Feed Linkup search results into an AI prompt to answer user questions with fresh, cited information. |
| **Lead enrichment** | Fetch a prospect's website and extract markdown to enrich a CRM record. |
| **Competitor monitoring** | Run scheduled deep searches restricted to competitor domains and log changes to a database. |
| **Page-to-database** | Fetch a news article, extract markdown, and add a new record with the content in a Softr table. |
## How to Connect Softr with Linkup
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a Linkup action.
3. Click **Connect Linkup** and paste your Linkup API key.
4. Your API key can be found on the Linkup dashboard at [app.linkup.so](https://app.linkup.so).
5. Configure your inputs (query, URL, filters, toggles) and save.
6. Activate your workflow.
---
# Firecrawl integration
Source: https://docs.softr.io/workflows/integrations/firecrawl
Connect Firecrawl with your Softr applications to pull content from the web without writing any scraping code. Build workflows that scrape specific URLs, run web searches, and feed the results into the rest of your Softr app.
## Overview
The Softr Firecrawl integration allows you to connect your no-code apps with Firecrawl's scraping and search API. Convert any webpage into clean markdown, HTML, or structured data, run natural-language searches across the web, news, and images, and use the results to enrich records, trigger follow-ups, or populate content — all without managing a headless browser or proxy fleet.
With Softr, you can scrape single URLs, search the web, and wire the responses into every downstream action in your workflow.
## Available Actions
### Scrape URL
Scrape a webpage and return its content in one or more formats: `markdown`, `html`, `rawHtml`, `screenshot`, or `summary`. You can choose to keep only the main content (strip nav, headers, footers, sidebars) or keep the full page. The response includes the requested formats plus page metadata (title, description, language, Open Graph tags, source URL, status code, content type).
### Search web
Run a natural-language query across the web, news articles, or image results. Pick one or more sources (`web`, `news`, `images`) and a per-source result limit. Each web result returns URL, title, and description; news results include snippet, date, and source; image results include image URL, dimensions, and title.
## Key Benefits
- **No-code simplicity:** Configure scraping and search actions visually in Softr — no browser automation or API plumbing.
- **Clean, LLM-ready output:** Markdown and structured JSON responses plug straight into downstream AI actions.
- **Multi-format scraping:** Ask for markdown, HTML, screenshots, or summaries from the same call.
- **Web, news and images in one action:** Search across multiple content types with a single query.
- **Automatic retries:** Firecrawl API calls are retried with exponential backoff on transient failures.
## Example Use Cases
| Use Case | Description |
| :---------------------------------------- | :------------------------------------------------------------------------------------------------------------ |
| **Enrich new leads with website content** | When a lead is created in your Softr app, scrape their company URL and save the summary alongside the record. |
| **AI-generated competitor briefs** | Scrape a competitor's pricing page daily and pipe the markdown into an AI summarization action. |
| **Knowledge base from search** | Run a Firecrawl search, scrape the top results, and store them in a Softr database as a searchable corpus. |
| **Automated news digest** | Search the news source for a topic and email a daily round-up to internal users. |
| **Link preview on form submission** | When a user submits a URL through a form, scrape it and display title/description back to them. |
## How to Connect Softr with Firecrawl
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a Firecrawl action (**Scrape URL** or **Search web**).
3. Click **Connect Firecrawl** and enter your Firecrawl API key.
4. Your API key can be found in your Firecrawl account under [API Keys](https://www.firecrawl.dev/app/api-keys). Keys are prefixed with `fc-` and do not expire.
5. Configure your inputs (target URL or search query, formats, limits) and save.
6. Activate your workflow.
## Usage and Billing Notes
- Each Firecrawl action consumes **5 workflow credits** per run.
- Firecrawl enforces per-team rate limits that vary by plan. If you hit a 429, Softr retries the call with exponential backoff before failing the action.
- Screenshot URLs returned by the scrape action expire 24 hours after generation — download or re-host them if you need to keep them long-term.
---
# Microsoft Excel integration
Source: https://docs.softr.io/workflows/integrations/microsoft-excel
Connect Microsoft Excel with your Softr applications to turn any workbook into a live backend for your no-code app. Capture form submissions, sync member data, power internal dashboards, and keep the spreadsheets your team already relies on up to date — automatically.
## Overview
The Softr Microsoft Excel integration lets your workflows read from and write to Excel workbooks stored in your Microsoft 365 account. Add rows when users submit forms, look up data to use in later steps, update rows when statuses change, and clean out stale entries — and start workflows the moment a new row lands in a sheet.
Excel fits naturally into Softr apps wherever your team already works in spreadsheets: request trackers, signup logs, lightweight CRMs, budget sheets, and reports that other departments maintain. Softr keeps the workbook and your app in sync without anyone copying data by hand.
## Available Actions
### Add row
Append a new row to a worksheet whenever a user submits a form, signs up, or triggers a workflow in your Softr app.
### Find row
Look up a single row by a matching value to use its data in the next workflow step.
### Find multiple rows
Retrieve several matching rows at once to power lists, reports, and bulk follow-up steps.
### Update row
Find a row by a matching value and update its fields when a record changes or a status moves forward.
### Update multiple rows
Apply the same update across all matching rows in one step — ideal for bulk status changes.
### Delete row
Remove a single row when a request is resolved, a user cancels, or stale data needs to go.
### Delete multiple rows
Clear out all matching rows at once to keep your workbook tidy after bulk actions or scheduled clean-ups.
## Available Triggers
### Row added
Starts a workflow when a new row appears in the worksheet you choose — so entries added directly in Excel can drive actions in Softr and beyond.
## Key Benefits
- **Your workbook as a backend:** Use the Excel files your team already maintains to power dynamic Softr apps — no migration needed.
- **Two-way flow:** Write app activity into Excel and react in Softr when rows are added on the spreadsheet side.
- **No more copy-paste:** Form submissions, sign-ups, and record changes land in the right worksheet automatically.
- **Bulk-friendly:** Update or clean up many rows in one step to keep large sheets manageable without manual work.
## Example Use Cases
| Use Case | Description |
| :--------------------------------- | :----------------------------------------------------------------------------------------------------------------- |
| **Form submissions to a workbook** | Capture every Softr form entry — leads, applications, requests — as a new row in an Excel worksheet. |
| **React to rows added in Excel** | When a teammate adds a row to a shared workbook, kick off a Softr workflow — notify, create records, or follow up. |
| **Member portal backed by Excel** | Keep a client or member list in Excel and update the matching row whenever users edit their details in your app. |
| **Status tracking** | When a record moves forward in your Softr admin dashboard, update the corresponding row so reports stay current. |
| **Scheduled clean-ups** | Run a recurring workflow that finds and deletes expired or resolved rows to keep the sheet lean. |
## How to Connect Softr with Microsoft Excel
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a Microsoft Excel action (or the **Row added** trigger).
3. Click **Connect Microsoft Excel** and sign in with your Microsoft account.
4. Authorize Softr to access the workbooks you want to use in your workflows.
5. Pick the workbook and worksheet you want to read from or write to.
6. Map fields from your Softr forms, records, or previous workflow steps to the columns in your sheet.
7. Save and activate your workflow.
---
# Microsoft Planner integration
Source: https://docs.softr.io/workflows/integrations/microsoft-planner
Connect Microsoft Planner with your Softr applications to turn what happens in your app into tasks your team actually sees. Build workflows that create Planner tasks the moment work appears — a client request comes in through a form, a record changes status, a new member joins — complete with the right bucket, assignees, due date, labels and checklist, so nothing waits for someone to copy it over by hand.
## Overview
The Softr Microsoft Planner integration links your no-code apps directly to the Planner plans your Microsoft 365 groups already use. Whenever a workflow runs, it can create a task in the plan and bucket you choose, assign it to the right people, set start and due dates, priority and progress, apply the plan's labels, and add a description, checklist items and attachment links — all mapped from your Softr forms, records and previous workflow steps.
This fits anywhere work is requested or tracked inside a Softr app: client portals where requests should become team tasks, internal tools where a status change kicks off follow-up work, or onboarding flows where every new sign-up needs the same set of to-dos.
## Available Actions
### Create task
Create a task in a Planner plan and bucket of your choice. Set the title, description, assignees, start and due dates, priority, progress and labels, add checklist items and attachment links, and get the created task back to use in the next step.
### Get task
Read a task by its id and get everything on it — title, bucket, assignees, dates, priority, progress, labels, description, checklist and attachments — ready to show in your app or use in the next step.
### List tasks
Pull the tasks of a plan, or of one bucket, and narrow them to a status (not started, in progress, completed) or to one person's assignments — to sync a board into a Softr table, build a "my tasks" view, or send a digest.
### Update task
Change a task from your workflow: rename it, move it to another bucket, reassign it, set new dates, priority or progress, swap its labels, replace the description or add checklist items. Fields you leave empty keep their current value.
### Delete task
Remove a task permanently when the request behind it is withdrawn or the work is no longer needed.
### List plans
Get every plan your connected account can see, with the Microsoft 365 group each one belongs to — to let users pick a plan in your app or to loop over plans in a report.
### Get plan
Read a plan and the names of its labels, so your workflow can pick the right label for a task or show the plan's setup in your app.
### List buckets
Get the buckets of a plan in board order, to route a task to the right column by name or mirror the board's stages in a Softr view.
### Create bucket
Add a new bucket to a plan — for example one column per new client, project phase or sprint created in your app.
## Key Benefits
- **No-code simplicity:** Pick your plan, bucket and labels from live dropdowns and map the rest from your app — no scripts, no Power Automate.
- **Tasks where your team works:** Work requested in Softr lands directly in the Planner boards your team already checks in Teams and Microsoft 365.
- **Complete tasks, not stubs:** Assignees, dates, priority, labels, checklist and attachments are set in one step, so the task is ready to work on when it appears.
- **Secure sign-in:** Connect with your Microsoft work account through Microsoft's own sign-in; Softr only asks for permission to manage tasks.
- **Ready for the next step:** Use the task's id and details downstream — save them to a record, notify the assignee, or link back to the request.
## Example Use Cases
| Use Case | Description |
| :-------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Client request intake** | When a client submits a request through your Softr portal, create a Planner task in the delivery team's plan with the request details, a due date and the account owner assigned. |
| **Onboarding checklists** | Each time a new customer or employee is added, create a task with a ready-made checklist of onboarding steps in the right bucket. |
| **Status-driven follow-ups** | When a record moves to "Approved" or "Needs review" in your app, create the follow-up task in the matching bucket with the right label — or move and reassign the existing one. |
| **Bug and feedback triage** | Turn feedback submitted in your app into prioritized tasks, with the submitter's screenshots attached as links. |
| **Content and campaign planning** | When a campaign or article is scheduled in your Softr app, create the production task with its start and due dates in the marketing plan. |
| **Recurring operations** | On a schedule, create the week's recurring tasks — reports, checks, reviews — so they appear in Planner without anyone remembering to add them. |
| **Board per client** | When a new client is added in your app, create a bucket named after them in the delivery plan, so their tasks have a home from day one. |
| **Team task dashboard** | List each plan's open tasks on a schedule and sync them into a Softr table, so clients or managers see progress without a Planner licence. |
## How to Connect Softr with Microsoft Planner
1. Open your Softr workspace and go to **Workflows**.
2. Create a new workflow or open an existing one, then add a Microsoft Planner action — work with tasks (create, get, list, update, delete), plans (list, get) or buckets (list, create).
3. In the **Account** field, click **Add another account** and sign in with your Microsoft work or school account. Grant Softr permission to manage your tasks when Microsoft asks.
4. Pick the **Plan** and **Bucket** the task should be created in — the dropdowns list the plans you have access to.
5. Map the **Title** and any other fields from your Softr forms, records, or previous workflow steps. Assignees can be entered as email addresses.
6. Save and activate your workflow.
---
# Mistral integration
Source: https://docs.softr.io/workflows/integrations/mistral
Connect Mistral with your Softr applications to add fast, cost-efficient AI text generation, summarization, and classification to your workflows. Handle high volumes of submissions, records, and messages with Europe's leading AI models — no code required.
## Overview
The Softr Mistral integration sends text from your workflows to Mistral's AI models and returns the result for use in any later step. Draft copy, condense long submissions into summaries, sort records into your own categories, or run any custom prompt — then store the output in a database, send it by email, or pass it to the next action.
In a typical Softr app, Mistral works on whatever your users hand you: a form block collects requests, members update records, new sign-ups arrive — and the workflow responds with clean summaries for your dashboards, routing labels for your team, and generated text ready to publish or send.
## Available Actions
### Custom prompt
Send your own prompt to Mistral — with data mapped in from forms, records, or earlier steps — and use the response anywhere in your workflow.
### Write
Generate original text such as email drafts, descriptions, replies, or personalized messages.
### Summarize Text
Condense long text — briefs, tickets, notes — into a short summary your team can scan.
### Categorize
Assign text to one of your predefined categories so submissions and records get routed automatically.
## Key Benefits
- **Fast and cost-efficient:** Mistral's models are built for speed, making them a great fit for high-volume workflows like triage and tagging.
- **No-code AI:** Configure prompts visually in the workflow editor — no API calls or scripts to maintain.
- **Your own Mistral account:** Connect with your API key and use your own models, limits, and billing — with data processed by a European AI provider.
- **Routing-ready output:** Use Categorize to produce clean labels you can branch on, filter with, or store in a record.
## Example Use Cases
| Use Case | Description |
| :--------------------------------- | :----------------------------------------------------------------------------------------------------- |
| **High-volume triage** | Categorize every incoming form submission and branch each one to the right queue, owner, or status. |
| **Summaries for admin dashboards** | Condense long requests and feedback into one-line summaries your team can review in a list block. |
| **Draft replies at scale** | Generate a suggested response for each new inquiry and store it with the record for one-click review. |
| **Consistent member content** | Rewrite user-submitted bios or listings into your app's tone before they go live in a portal. |
| **Tag and organize records** | Label database records by topic or sentiment as they're created, keeping filters and views meaningful. |
## How to Connect Softr with Mistral
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a Mistral action.
3. Click **Connect Mistral** and paste your Mistral API key. You can create one in [Mistral's La Plateforme console](https://console.mistral.ai) under **API Keys**.
4. Choose the model and write your instructions or prompt.
5. Map fields from your Softr forms, records, or previous workflow steps into the prompt inputs.
6. Save and activate your workflow.
---
# monday.com integration
Source: https://docs.softr.io/workflows/integrations/monday
Connect monday.com with your Softr applications to turn boards into living, member-facing apps. Capture intake from Softr forms, surface monday.com items in client portals, and keep project data in sync across your team — all without code.
## Overview
The Softr monday.com integration lets you read from and write to any monday.com board straight from your Softr workflows. Trigger automations on form submissions, button clicks, or record changes to create new items, update statuses, fetch project data, or clean up stale records — keeping monday.com as the single source of truth for your team while Softr handles the front-end experience.
This fits naturally anywhere your Softr app collects or displays operational data: client request portals where each submission becomes a monday.com item, internal dashboards built on top of your existing boards, project status pages for clients, intake forms that turn into tasks, and admin tools that let your team review and update work without leaving Softr.
## Available Actions
### Add record
Create a new item on a monday.com board with column values mapped from your Softr form, record, or workflow inputs.
### Get record
Retrieve a single monday.com item by ID to display its details in a Softr page or use its values in later workflow steps.
### Get records
Fetch multiple items from a board at once — perfect for powering Softr lists, tables, or dashboards with live monday.com data.
### Update record
Change column values on an existing monday.com item when something changes in your Softr app, like a status update, assignment, or due date edit.
### Update records
Update several monday.com items in a single step — handy for bulk status changes, reassignments, or syncing a batch of records.
### Delete record
Remove a single item from a monday.com board, for example when a request is canceled or archived in your Softr app.
### Delete records
Delete multiple monday.com items in one step to clean up completed, rejected, or expired records in bulk.
## Key Benefits
- **No-code project automation:** Build workflows between Softr and monday.com visually — no scripts, no API calls, no glue code.
- **Single source of truth:** Keep monday.com as your operational hub while Softr handles the customer-facing or internal interface.
- **Real-time collaboration:** Items created or updated from Softr show up immediately in monday.com for your team to act on.
- **Bulk-friendly:** Create, update, or delete many items at once to keep large boards clean and current.
- **Member-facing or internal:** Power client portals, intake forms, and back-office dashboards from the same monday.com board.
## Example Use Cases
| Use Case | Description |
| :------------------------------- | :-------------------------------------------------------------------------------------------------------------------- |
| **Client request portal** | Let clients submit requests through a Softr form and automatically create a new item on your monday.com intake board. |
| **Project status dashboard** | Display live project items from monday.com inside a Softr list block so clients can track progress without a seat. |
| **Internal team dashboard** | Build a custom admin view on top of an existing monday.com board, with filters and actions tailored to your team. |
| **Intake form to task pipeline** | Turn lead, support, or hiring form submissions into structured monday.com items routed to the right group. |
| **Status updates from Softr** | Let team members or clients update an item's status, assignee, or due date directly from a Softr record page. |
| **Cleanup and archival** | Bulk-delete completed or canceled items from a monday.com board on a schedule or via an admin button in Softr. |
## How to Connect Softr with monday.com
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a monday.com action.
3. Click **Connect to monday.com** and authorize Softr to access your account.
4. Pick the board you want to read from or write to.
5. Map your Softr form fields, record values, or previous workflow outputs to the monday.com columns.
6. Save and activate your workflow.
---
# Notion integration
Source: https://docs.softr.io/workflows/integrations/notion
Connect Notion with your Softr applications to turn your Notion databases into a living backend for forms, member portals, and lightweight CMSes. Capture submissions, surface records to your users, start workflows when a page is added or edited in Notion, and keep everything in sync — without leaving the tools your team already loves.
## Overview
The Softr Notion integration lets your no-code apps read from and write to Notion databases in real time. Whenever a user submits a form, signs up, or updates a record in Softr, you can create, fetch, edit, or remove the matching page in Notion — keeping your operations team working in their familiar workspace while your customers interact with a polished Softr front end. It also works the other way round: the **Record created** and **Record updated** triggers start a workflow when a page is added or edited in a Notion database, so your app can follow what your team does in Notion.
This pairing fits naturally wherever Notion is already the source of truth: applicant trackers, content calendars, customer directories, project boards, internal wikis, and client intake systems. Your team manages the data in Notion; your members and visitors see and act on it through Softr blocks, forms, and member dashboards.
## Available Actions
### Add record
Create a new page in a Notion database — perfect for capturing form submissions, new sign-ups, or any record your Softr app generates.
### Get record
Fetch a single page from a Notion database by its ID, ready to display in a detail view or pass to the next workflow step.
### Get records
Retrieve multiple pages from a Notion database at once, with optional filters, so you can power Softr lists with live Notion data.
### Update record
Modify the properties of an existing page in a Notion database whenever a status changes, an admin reviews a submission, or a member edits their own profile.
### Update records
Update several pages in a Notion database in a single workflow step — ideal for bulk status changes, batch approvals, or recurring clean-up jobs.
### Delete record
Remove a single page from a Notion database when an item is archived, rejected, or no longer relevant.
### Delete records
Remove multiple pages from a Notion database in one go, keeping your workspace tidy without manual housekeeping.
## Available Triggers
Notion triggers use background polling: Softr checks the database for changes at a regular interval, so a workflow starts shortly after the change rather than the moment it happens. The interval depends on your plan (every minute on Professional plans and above) and is shown on the trigger in the workflow builder. Each trigger watches one Notion database.
### Record created
Starts a workflow when a new page is added to the selected Notion database — a new applicant, a new content entry, a new row your team typed in. Run a test on the trigger to pull a recent page and see the properties available to later steps.
### Record updated
Starts a workflow when a page in the selected Notion database is edited — a status changes, an owner is assigned, a date is set. Add a [Filter](/workflows/advanced-concepts#filter) step after the trigger to act only on the changes you care about.
## Key Benefits
- **No-code Notion backend:** Use any Notion database as the data layer behind your Softr app, with no scripts or third-party glue tools.
- **Real-time sync:** Form submissions, profile edits, and status changes flow into Notion the moment they happen.
- **Familiar workspace for your team:** Your operators, editors, and admins keep working in Notion while customers interact through Softr.
- **Bidirectional workflows:** Read from Notion to power lists and dashboards, or write to Notion to capture activity from your app.
- **Bulk-friendly automations:** Update or clean up many records at once with the multi-record actions.
- **React to changes in Notion:** Start a workflow when a page is added or edited in a Notion database, so notifications, syncs, and follow-ups happen without anyone leaving Notion.
## Example Use Cases
| Use Case | Description |
| :------------------------------ | :--------------------------------------------------------------------------------------------------------------------- |
| **Form-to-Notion intake** | Capture Softr form submissions — applications, contact requests, feedback — as new pages in a Notion database. |
| **Member portal on Notion** | Power a member dashboard with Notion data: each member sees and edits only the rows linked to their account. |
| **Lightweight CMS for content** | Let editors manage articles, listings, or events in Notion and surface them to visitors through Softr list blocks. |
| **Applicant or lead tracker** | Push new leads into a Notion CRM database, then update their stage as your team moves them through the pipeline. |
| **Status-driven notifications** | Update a Notion page when a record changes in Softr, so your operations team always sees the latest state in context. |
| **Admin clean-up workflows** | Bulk-archive or delete outdated Notion pages on a schedule or when a record is closed in your Softr admin tool. |
| **New entry alerts** | When a page is added to a Notion database, notify your team in Slack or send a confirmation email to the submitter. |
| **Notion-to-Softr sync** | When a page is edited in Notion, update the matching record in your Softr database so your app shows the latest state. |
## How to Connect Softr with Notion
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a Notion trigger, such as Record created, or a Notion action, such as Add record.
3. Click **Connect to Notion** and sign in to authorize Softr to access your Notion workspace.
4. Choose which pages and databases Softr should be able to read from and write to.
5. Pick the database you want to use.
6. For an action, map your Softr form fields, record properties, or previous workflow outputs to the matching Notion database properties. For a trigger, run a test to pull a sample page.
7. Save and activate your workflow.
---
# OpenAI integration
Source: https://docs.softr.io/workflows/integrations/openai
Connect OpenAI with your Softr applications to add GPT-powered text generation, summarization, classification, and image creation to your workflows. Turn what your users submit into drafts, summaries, labels, and visuals — without writing a line of code.
## Overview
The Softr OpenAI integration sends content from your workflows to OpenAI's models and returns the result for use in any later step. Generate text with GPT models, classify and summarize what users submit, or create images from a text prompt — then store the output in a database, send it by email, or display it in your app.
In a typical Softr app, OpenAI picks up where your users leave off: a lead fills in a form block, a member posts a listing, an operations record changes status — and the workflow responds with generated copy, a summary for your team, a category to branch on, or a fresh image for the record.
## Available Actions
### Custom prompt
Send your own prompt to OpenAI — with data mapped in from forms, records, or earlier steps — and use the response anywhere in your workflow.
### Write
Generate original text such as email drafts, product descriptions, social posts, or personalized messages.
### Summarize
Condense long text — applications, feedback, meeting notes — into a short summary your team can scan at a glance.
### Categorize
Assign text to one of your predefined categories so submissions and records get routed automatically.
### Generate image (Image 2)
Create an image from a text prompt and use the result in your app — as a record attachment, a listing visual, or an email asset.
## Key Benefits
- **Text and images in one integration:** Generate copy and visuals from the same workflow, powered by your OpenAI account.
- **No-code AI:** Configure prompts visually in the workflow editor — no API calls or scripts to maintain.
- **Your own OpenAI account:** Connect with your API key and use your OpenAI models and usage limits directly.
- **Built for routing:** Use Categorize to produce clean labels you can branch on, filter with, or store in a record.
## Example Use Cases
| Use Case | Description |
| :-------------------------------- | :------------------------------------------------------------------------------------------------------------ |
| **Auto-generate listing content** | When a member adds a record through your portal, write a polished description and save it back to the record. |
| **Illustrate records** | Generate an image for each new product, event, or listing and attach it automatically. |
| **Score and route leads** | Categorize incoming form submissions and branch the workflow by lead type or urgency. |
| **Summaries for your dashboard** | Summarize long applications or feedback entries so your admin dashboard shows the gist, not the wall of text. |
| **Personalized member emails** | When a user signs up, write a welcome email tailored to their profile answers and send it automatically. |
## How to Connect Softr with OpenAI
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add an OpenAI action.
3. Click **Connect OpenAI** and paste your OpenAI API key. You can create one in the [OpenAI platform dashboard](https://platform.openai.com) under **API keys**.
4. Choose the model and write your instructions or prompt.
5. Map fields from your Softr forms, records, or previous workflow steps into the prompt inputs.
6. Save and activate your workflow.
---
# Outlook integration
Source: https://docs.softr.io/workflows/integrations/outlook
Connect Outlook with your Softr applications to send transactional emails, customer confirmations, and internal alerts straight from your no-code app — and to start workflows when an email arrives. Keep your members, your team, and your shared inboxes in sync — without leaving Softr.
## Overview
The Softr Outlook integration lets you send emails from your Microsoft 365 account whenever something happens in your Softr app. Trigger emails from form submissions, new member sign-ups, status changes, or scheduled workflows, and deliver them straight from the Outlook address your customers already know and trust.
Whether you're confirming a booking from a member portal, alerting a shared support inbox about a new request, or sending a personalized follow-up after a form submission, Outlook fits naturally into the apps your team and customers already rely on every day.
## Available Actions
### Send email
Send an email from your connected Outlook account to one or more recipients, with a custom subject, body, and optional CC, BCC, and attachments — all triggered by events inside your Softr app.
## Available Triggers
### Email received
Start a workflow whenever a new email lands in an Outlook folder you pick — optionally only for emails from specific senders — with the sender, recipients, subject, body, and attachments ready to use in the next steps.
## Key Benefits
- **No-code simplicity:** Build email automations visually in Softr — no SMTP setup, no developer required.
- **Send from your real address:** Emails go out from your Microsoft 365 mailbox, so customers see a sender they recognize.
- **Personalized at scale:** Pull form fields, member details, and record data into every message automatically.
- **Team-ready inboxes:** Route notifications to shared Outlook inboxes so the whole team can pick up replies.
- **Reliable delivery:** Lean on Microsoft 365 deliverability for transactional and member-facing email.
## Example Use Cases
| Use Case | Description |
| :-------------------------------- | :------------------------------------------------------------------------------------------------------------------------ |
| **Form submission confirmations** | Send a personalized thank-you email to anyone who submits a contact, booking, or application form in Softr. |
| **New member welcome emails** | Email new sign-ups from a member portal with onboarding instructions, login links, or next-step resources. |
| **Internal team alerts** | Notify a shared Outlook inbox whenever a new lead, support ticket, or high-priority record lands in your app. |
| **Status change notifications** | Email a customer when their order, application, or request moves to a new status in your Softr database. |
| **Approval and review requests** | Send an approver an email with the relevant record details whenever a member submits something for review. |
| **Inbound email to records** | Turn order confirmations, support requests, or replies arriving in an Outlook folder into records in your Softr database. |
| **Scheduled digests and reports** | Email weekly or daily summaries of new records, sign-ups, or activity to managers and stakeholders. |
## How to Connect Softr with Outlook
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add the **Send email** Outlook action, or start it with the **Email received** Outlook trigger.
3. Click **Connect to Outlook** and sign in with your Microsoft 365 account.
4. Approve the requested permissions so Softr can send and read email on your behalf.
5. Choose the trigger that should send it (form submission, sign-up, record update, schedule).
6. Fill in recipients, subject, and body — using fields from your Softr forms, records, or previous workflow steps to personalize the message.
7. Save and activate your workflow.
---
# Pinecone integration
Source: https://docs.softr.io/workflows/integrations/pinecone
Connect Pinecone with your Softr applications to power semantic search, retrieval-augmented generation (RAG), and other AI features. Build workflows that create indexes, store text records, and search for semantically similar content — all without code.
## Overview
The Softr Pinecone integration allows you to connect your no-code apps with the Pinecone vector database using **integrated embedding**. Create serverless indexes backed by a built-in embedding model, upsert raw text records (Pinecone embeds them server-side), and search with natural-language query text. Use the results to ground LLM prompts, build smart search experiences, or recommend related content.
With Softr, you can configure end-to-end semantic workflows: index your knowledge base whenever new content is added, then search Pinecone whenever a user asks a question — all without writing a single line of code, and without managing embeddings yourself.
## Available Actions
### Create index
Create a new serverless Pinecone index with integrated embedding. Choose an embedding model — `multilingual-e5-large` (dense), `llama-text-embed-v2` (dense), or `pinecone-sparse-english-v0` (sparse) — a cloud (AWS, GCP, or Azure), and a region. Optionally set deletion protection and tags. The index name is normalized to lowercase alphanumeric and hyphens (max 45 characters). The distance metric is determined automatically by the embedding model.
Indexes created here are automatically configured so that records use the **`chunk_text`** field for embedding — which is what the **Upsert records** action expects.
### List indexes
List every index in the connected Pinecone project.
### Describe index
Get full details for a single index — including its data-plane host. Useful for checking readiness or confirming an index's configuration.
### Delete index
Delete a Pinecone index permanently. Pinecone rejects the deletion when the index has deletion protection enabled (set at creation time).
### Upsert records
Insert or update raw text records into an index. Pinecone embeds the text server-side, so you don't supply vectors yourself. Up to **96 records** per request.
Each record must include:
- **`_id`** — a unique string identifier for the record.
- **`chunk_text`** — the text to embed. This field is **required** and must be non-blank.
- Any other keys (e.g. `category`) — stored as **metadata**, which you can filter and return in the **Search records** action.
```json
[
{ "_id": "rec1", "chunk_text": "Hello world", "category": "greeting" }
]
```
> **Important — the text field must be named `chunk_text`.** If you created your index with Softr's **Create index** action, it's already configured for `chunk_text` and there's nothing to do. If you created the index in the Pinecone console or via the SDK, its field map defaults to `text` — you must set the field map's text field to **`chunk_text`**, otherwise upserts will fail validation.
### Search records
Search an index using natural-language query text — Pinecone embeds it server-side. Request top-K results (1–10,000, default 10), optionally filter by metadata, and optionally restrict which record fields are returned. The metadata `filter` and `fields` inputs operate on the extra keys you stored on each record at upsert time (anything beyond `_id` and `chunk_text`).
## Key Benefits
- **No-code simplicity:** Create Pinecone indexes and manage text records from Softr's visual workflow builder — no SDK or scripting required.
- **Integrated embedding:** Skip the embedding step entirely — let Pinecone embed your text records and search queries server-side using its built-in models.
- **Real-time semantic search:** Surface relevant content to your users instantly based on meaning, not keywords.
- **AI workflow ready:** Combine Pinecone with the OpenAI, Anthropic, or other AI actions to build retrieval-augmented generation pipelines.
## Example Use Cases
| Use Case | Description |
| :------------------------------------ | :-------------------------------------------------------------------------------------------------------- |
| **RAG over your knowledge base** | Upsert document text into Pinecone, then search for relevant context to ground an AI assistant's answers. |
| **Semantic search for help articles** | Index support content and surface the closest matches when a user submits a support form. |
| **Personalized recommendations** | Upsert profile or item text and search Pinecone to find the most similar items, products, or other users. |
| **Duplicate detection** | Search for near-duplicate records before adding new ones to a database. |
| **AI-powered tagging** | Search records by similarity to known categories and assign tags automatically. |
## How to Connect Softr with Pinecone
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a Pinecone action.
3. In the **Account** field, connect your Pinecone account and enter **Your Pinecone API key** (it starts with `pcsk_`).
4. Your API key can be found in the [Pinecone console](https://app.pinecone.io) under **Project → API Keys**.
5. Configure your inputs (index, records, query text, etc.) and save.
6. Activate your workflow.
---
# Postmark integration
Source: https://docs.softr.io/workflows/integrations/postmark
Connect Postmark with your Softr applications to send fast, reliable transactional emails straight to your users' inboxes. Power welcome emails, password resets, receipts, and customer-facing confirmations from your Softr app — with the deliverability your business depends on.
## Overview
The Softr Postmark integration lets you trigger transactional emails from any event in your Softr app — form submissions, member sign-ups, record updates, status changes, or scheduled workflows. Unlike personal inbox tools, Postmark is purpose-built for high-volume transactional mail, so messages land in the inbox instead of the promotions tab.
This is the right fit when your Softr app needs to send branded, reliable emails from your own domain at scale: onboarding flows for new members, order or booking confirmations, account notifications, password and access emails, and any other automated communication where deliverability matters.
## Available Actions
### Send email
Send a transactional email from your verified Postmark sender to one or more recipients, with custom subject, body, and optional HTML content — triggered by any event in your Softr app.
## Key Benefits
- **Industry-leading deliverability:** Postmark's transactional infrastructure consistently lands emails in the inbox, not the spam folder.
- **Built for scale:** Send thousands of emails from your Softr app without throttling, queues, or manual retries.
- **Branded from your domain:** Send from your own verified domain so customers see your brand, not a third-party address.
- **No-code setup:** Wire emails into your Softr workflows visually — no SMTP configuration, no developer required.
- **Real-time and reliable:** Trigger emails the moment a user submits a form, signs up, or updates a record, with the speed your customers expect.
## Example Use Cases
| Use Case | Description |
| :---------------------------------- | :-------------------------------------------------------------------------------------------------------------- |
| **Welcome new members** | Send a branded welcome email the moment someone signs up to your Softr member portal. |
| **Password reset and access** | Deliver password reset and account-access emails reliably so members never get locked out. |
| **Order and booking confirmations** | Email customers a confirmation as soon as they submit an order, booking, or application form in your Softr app. |
| **Receipts and invoices** | Automatically send a receipt or invoice email when a payment or transaction is recorded. |
| **Status change notifications** | Alert customers when their request, application, or order changes status in your Softr database. |
| **Scheduled customer updates** | Send recurring transactional emails — renewal reminders, expiry notices, or account summaries — on a schedule. |
## How to Connect Softr with Postmark
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add the **Send email** Postmark action.
3. Click **Connect to Postmark** and paste your Server API token.
4. Your Server API token can be found in your Postmark account under **Servers** — open the server you want to send from and copy its **Server API token**.
5. Choose your verified sender address.
6. Map recipient, subject, and message content from your Softr forms, records, or previous workflow steps.
7. Save and activate your workflow.
---
# QuickBooks integration
Source: https://docs.softr.io/workflows/integrations/quickbooks
Connect QuickBooks Online with your Softr applications to keep your books in sync with your app — create customers and invoices the moment something happens in Softr, look up financial records on demand, record payments and vendor bills, and react instantly when anything changes in QuickBooks. Build billing portals and finance workflows on top of your live accounting data, without code.
## Overview
The Softr QuickBooks integration lets your app read and write the records your accounting runs on: customers, invoices, vendors, bills, items, and payments. Create or update a record, fetch a single one by ID, or pull a filtered list to display and act on inside Softr. Every action returns the record it created, updated, or fetched, so you can use it in any downstream workflow step.
This unlocks the patterns Softr customers reach for first: turning a form submission into a QuickBooks customer, raising and emailing an invoice when a booking is confirmed, surfacing outstanding invoices in a client portal, recording payments from an app, and kicking off follow-up automations the moment an invoice or customer changes in QuickBooks — keeping your app and your books aligned both ways.
## Available Actions
### Customers
#### Create customer
Add a new customer to QuickBooks — typically from a Softr signup form, an onboarding flow, or a "new client" record action. Set the display name (required), contact name and company, email, phone, billing address, preferred delivery method, and whether the customer is taxable.
#### Get customer
Look up a single customer by ID to surface their billing details on a member's account page or an admin record view.
#### List customers
Retrieve customers to power admin dashboards, client directories, or a picker on a form. Set a limit and, optionally, a filter to narrow the results (for example, only active customers).
#### Update customer
Keep QuickBooks in sync with your app — refresh a customer's name, contact details, billing address, or status when the matching record changes in Softr. Updates are sparse: only the fields you fill in are changed, and everything else is left untouched.
### Invoices
#### Create invoice
Raise a sales invoice for a customer, with one or more line items (amount, item, quantity, description, tax code), transaction and due dates, document number, billing email, customer memo, and billing address — for example, billing a client automatically after an order or a confirmed booking.
#### Get invoice
Fetch a single invoice by ID to read its amount, balance, status, and line items downstream.
#### List invoices
Retrieve invoices — for example, to show a client their invoice history in a portal, or to drive a payment-reminder workflow. Supports a limit and an optional filter.
#### Update invoice
Change an existing invoice's transaction or due date, document number, billing email, or customer memo as records change in your app.
#### Send invoice
Email an invoice to a customer through QuickBooks. Provide the invoice ID and the recipient address, and QuickBooks delivers the invoice and marks it as sent.
#### Void invoice
Void an invoice that should not be paid. The invoice stays in QuickBooks for your audit trail with its amounts zeroed out.
#### Delete invoice
Permanently remove an invoice from QuickBooks. Use **Void invoice** instead when you need to keep a record of the transaction.
### Vendors
#### Create vendor
Add a supplier to QuickBooks with their display name (required), contact details, company, account number, billing address, and 1099 status.
#### Get vendor
Fetch a single vendor by ID to reuse their details in a later workflow step.
#### List vendors
Retrieve vendors to display in Softr, sync to a Softr database, or loop over in a workflow. Supports a limit and an optional filter.
#### Update vendor
Update a vendor's details or deactivate them when the matching record changes in your app. Like customer updates, only the fields you provide are changed.
### Bills
#### Create bill
Record a vendor bill with one or more expense lines. Each line can be item-based (linked to a product or service) or account-based (linked to an expense account), with an amount and description, plus transaction and due dates, a document number, and a private note.
#### Get bill
Fetch a single bill by ID to read its vendor, amount, balance, and lines.
#### List bills
Retrieve bills — for example, to build an accounts-payable view or an approval queue inside Softr. Supports a limit and an optional filter.
### Items
#### Get item
Look up a single product or service item by ID, for example to read its name, price, or type before adding it to an invoice.
#### List items
Retrieve your products and services to display in Softr or to populate a selection on a form. Supports a limit and an optional filter.
### Payments
#### Create payment
Record a customer payment in QuickBooks with the amount, transaction date, reference number, and a private note — for example after a member pays through your app.
#### Get payment
Fetch a single payment by ID to display or reconcile it downstream.
#### List payments
Retrieve payments to build reconciliation views, a client's payment history, or a finance dashboard. Supports a limit and an optional filter.
## Available Triggers
### Entity changed
Fires when a record is created or updated in QuickBooks. Choose the entity to listen to — customer, invoice, vendor, bill, item, or payment — and whether the trigger runs on **created**, **updated**, or **both**. Voiding a transaction counts as an update.
QuickBooks delivers only the change details — the realm (company) ID, entity name, entity ID, operation, and the time it was last updated — not the full record. Chain the matching **Get** action (for example **Get invoice**) after the trigger, using the entity ID, to fetch the record's current state and use it in the rest of your workflow.
## Key Benefits
- **No-code accounting automation:** Configure QuickBooks actions and triggers visually in Softr — no API setup, no scripts.
- **Two-way sync:** Push customers, invoices, bills, and payments into QuickBooks and react to changes coming back out, so your app and your books stay aligned.
- **Live financial data in your app:** Pull customers, invoices, and payments into list and detail blocks to build billing portals and finance dashboards.
- **Pick records from dropdowns:** Customers, items, vendors, accounts, and tax codes load straight from your QuickBooks company, so you select them instead of hunting for IDs.
- **Safe updates:** Update actions only change the fields you fill in, so partial updates from a Softr form never wipe the rest of the record.
- **Reusable outputs:** Every action returns the full record, ready to drop into emails, database records, Slack messages, or any other workflow step.
## Example Use Cases
| Use Case | Description |
| :------------------------------ | :------------------------------------------------------------------------------------------------------------------ |
| **New customer to QuickBooks** | Create a QuickBooks customer automatically when someone signs up or submits an onboarding form in your Softr app. |
| **Invoice on order or booking** | Raise an invoice when a customer places an order or confirms a booking, then email it with **Send invoice**. |
| **Client billing portal** | Use **List invoices** and **List payments** to show clients their invoices and payment history inside Softr. |
| **Accounts payable queue** | Create vendor bills from a Softr form and surface open bills in an internal approval dashboard. |
| **Payment follow-ups** | Trigger on a changed invoice, fetch it with **Get invoice**, and send a reminder or update a record when it's paid. |
| **Keep records in sync** | Update a QuickBooks customer or vendor whenever the matching record changes in your Softr database. |
| **Finance dashboard** | Pull invoices, bills, and payments into a Softr admin dashboard for a real-time view of your books. |
## How to Connect Softr with QuickBooks
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a QuickBooks action (or the **Entity changed** trigger).
3. Click **Connect to QuickBooks** and sign in with your Intuit account, then select the company you want to connect and authorize the requested permissions.
4. Pick the connected QuickBooks account on the action or trigger (you can connect more than one company).
5. Map fields from your Softr forms, records, or previous workflow steps to the action's inputs — for example, customer details or invoice line items. Fields like customer, item, vendor, account, and tax code are offered as dropdowns loaded from your QuickBooks company.
6. Save and activate your workflow.
---
# Replicate integration
Source: https://docs.softr.io/workflows/integrations/replicate
Generate AI images directly from your Softr workflows. The Replicate integration gives your no-code app access to a curated set of image-generation models — pick the one that fits your need, drop in a text prompt, and get back a finished image as part of any automation.
## Overview
The Softr Replicate integration runs image-generation models hosted on Replicate from your workflows. Two actions ship today: **Pruna via Replicate** (a model selector covering several optimized variants like Z-Image Turbo, Flux Fast, P-Image, and SDXL Lightning) and **Flux Schnell via Replicate** (Black Forest Labs' 4-step distilled image model). One Replicate API token covers them all, and the same token will cover any future Replicate actions you add.
Inside a Softr app, this means form submissions can produce hero images for membership cards, list rows can spawn personalized illustrations, AI assistants can generate visuals on demand, and onboarding flows can hand new users an avatar built from their bio. The action returns an image URL you can drop into a Files field, attach to an email, or hand off to any downstream workflow step.
## Available Actions
### Pruna via Replicate
Generate an image with one of Pruna AI's optimized models — fast, production-ready, and tuned for quality at speed. Pick the model that matches your style preference; the rest of the inputs (prompt, aspect ratio, output format) stay the same regardless of which model you choose.
### Flux Schnell via Replicate
Generate up to four images at a time with Black Forest Labs' Flux Schnell — a 4-step distilled model designed for cinematic output in under three seconds. Pass an optional seed for reproducible results, or leave it empty to get fresh variations on every run.
## Key Benefits
- **No-code image generation:** Drop a prompt into a workflow step and get back a usable image URL — no API plumbing, no token juggling.
- **One credential, every model:** A single Replicate API token works for every action under the Replicate provider, so adding new image actions later doesn't mean reconnecting.
- **Reproducible when you need it:** Pass an optional seed to regenerate the same image deterministically — useful for template previews and A/B tests.
- **Fast by default:** Both actions ship with Replicate's accelerated inference paths enabled, so most generations finish inside a few seconds.
## Example Use Cases
| Use Case | Description |
| :------------------------------ | :--------------------------------------------------------------------------------------------------- |
| **Personalized hero images** | When a user signs up, generate a custom banner from their bio and store the URL on their profile. |
| **Per-record illustrations** | For every new record in a listing, generate a thumbnail from the record's prompt or description. |
| **Form-driven creative briefs** | Turn a form submission into four image variations Flux Schnell renders in parallel for review. |
| **AI-assistant visuals** | Let a Softr AI assistant call the action mid-conversation when a user asks for a visual. |
| **Marketing asset batches** | Loop over a list of campaign briefs to produce a gallery of generated images for the marketing team. |
## How to Connect Softr with Replicate
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add the **Replicate → Pruna via Replicate** or **Replicate → Flux Schnell via Replicate** action.
3. Click **Connect Replicate** and paste your Replicate API token.
4. To create a token, sign in to [Replicate](https://replicate.com/account/api-tokens) and generate a new token (must start with `r8_`). The same token works for every Replicate action, current and future.
5. Choose a model (for the Pruna action) or accept the Flux Schnell defaults, write your prompt, and configure aspect ratio and output options.
6. Save and activate your workflow.
---
# Resend integration
Source: https://docs.softr.io/workflows/integrations/resend
Connect Resend with your Softr applications to send reliable transactional email and manage your audience from your workflows. Deliver confirmations, notifications, and scheduled messages the moment users act in your app — and keep contacts and segments in sync automatically.
## Overview
The Softr Resend integration lets your workflows send emails through Resend and manage the contacts and segments behind them. Send a message when a form is submitted or a record changes, schedule or cancel deliveries, and add every new sign-up to the right audience segment — all from the workflow editor.
In a typical Softr app, Resend handles the email side of every interaction: a client books through your portal and gets a confirmation, a new member signs up and joins your onboarding segment, an order status changes and the customer hears about it — reliably and on brand.
## Available Actions
### Send email
Send a transactional or notification email — confirmation, receipt, alert — with content built from your app's data.
### Get email
Look up a sent email to check its status or reuse its details in a later step.
### Reschedule email
Change the delivery time of a scheduled email when plans move.
### Cancel email
Stop a scheduled email from going out — for example, when a user cancels or completes the action early.
### Create contact
Add a new contact to your Resend audience when someone signs up or submits a form.
### Get contact
Look up a contact's details to use in the next workflow step.
### List contacts
Retrieve contacts from your audience to power digests, exports, or bulk follow-ups.
### Delete contact
Remove a contact when a user unsubscribes or closes their account.
### Create segment
Create a new audience segment to group contacts — by plan, interest, or lifecycle stage.
### Delete segment
Remove a segment you no longer need.
### Add contact to segment
Place a contact into a segment when they take an action — upgrade, register, or express an interest.
### Remove contact from segment
Take a contact out of a segment when their status changes.
## Key Benefits
- **Email that reacts to your app:** Every form submission, sign-up, and record change can send exactly the right message, automatically.
- **Audience stays current:** Contacts and segments update themselves as users act — no manual list maintenance.
- **Scheduling built in:** Schedule, reschedule, or cancel deliveries from the same workflow that created them.
- **No-code setup:** Configure sender, recipients, and content visually, mapping in data from any step.
## Example Use Cases
| Use Case | Description |
| :------------------------ | :---------------------------------------------------------------------------------------------------------------- |
| **Instant confirmations** | Send a branded confirmation email the moment a user submits a form or places a request in your app. |
| **Onboarding sequences** | Add each new member to an onboarding segment and send a welcome email built from their sign-up details. |
| **Status notifications** | Email customers when the status of their order, application, or ticket changes in your admin dashboard. |
| **Smart reminders** | Schedule a reminder email when a booking is made — and cancel it automatically if the user completes early. |
| **Segment upkeep** | Move contacts between segments as their plan, role, or activity changes so campaigns always hit the right people. |
## How to Connect Softr with Resend
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a Resend action.
3. Click **Connect Resend** and paste your Resend API key. You can create one in the [Resend dashboard](https://resend.com) under **API Keys**.
4. Configure the action — recipients, subject, and content for emails, or the audience details for contact actions.
5. Map fields from your Softr forms, records, or previous workflow steps to the action's inputs.
6. Save and activate your workflow.
---
# Salesforce integration
Source: https://docs.softr.io/workflows/integrations/salesforce
Connect Salesforce to Softr workflows to automate CRM tasks, sync customer data, and keep your sales pipeline up to date. You don't need to write code.

_The five Salesforce actions in the workflow builder_
## Overview
The Softr Salesforce integration lets you create, update, retrieve, and delete records in any Salesforce object. This includes Contacts, Leads, Opportunities, Accounts, and custom objects. Start a [workflow](/workflows/workflows) from a form submission, a user sign-up, a record change, or any other event in your Softr app, and Salesforce reflects the change right away.
Use Softr workflows to connect your customer portals and internal tools to Salesforce. Your team gets accurate data without manual entry.
## Available actions
### Create record
Add a new record to any Salesforce object. Select the object type (Contact, Lead, Opportunity, Account, or a custom object). Then map fields from your Softr form or database to the Salesforce object fields.
### Update record
Update an existing Salesforce record by ID. Select the object type, provide the record ID, and map the fields you want to change. For example, update a phone number, change a deal stage, or reassign an account owner.
### Get record
Retrieve a single Salesforce record by its ID. Select the object type and provide the record ID. All fields of the record are available in later workflow steps.
### Get many records
Fetch several records from any Salesforce object. Optionally filter the results with a SOQL WHERE clause (for example, `LastName = 'Doe' AND AccountId = '001abc'`) and set a limit on the number of records returned.
### Delete record
Permanently remove a record from any Salesforce object by ID. Start this workflow from an admin action button or a data-cleanup workflow.
## Key benefits
- **Works with any Salesforce object:** Automate Contacts, Leads, Opportunities, Accounts, and your own custom objects.
- **No manual data entry:** Push data from Softr forms and portals into Salesforce without copy and paste.
- **Real-time CRM sync:** Update Salesforce as soon as something happens in your Softr app, such as a new sign-up, a form submission, or a record update.
- **Customer portals:** Build client-facing portals in Softr that read from and write to Salesforce.
- **No Salesforce admin needed:** Configure CRM automations visually in Softr. You don't need custom Apex code or complex Salesforce flows.
- **Multi-step workflows:** Chain Salesforce actions with other integrations. For example, send a Slack notification after you create a record, or email a confirmation after a deal closes.
## Example use cases
| Use case | Description |
| :-------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------- |
| **Lead capture from forms** | A visitor submits a contact form in your Softr app. The workflow creates a Salesforce Lead or Contact with their details. |
| **Member portal sync** | A new user signs up to your Softr portal. The workflow creates a Salesforce Contact and assigns it to the right account. |
| **CRM data enrichment** | Customers update their own profile in a Softr portal. The changes flow into their Salesforce record. |
| **Deal pipeline automation** | A form is submitted or a status changes in Softr. The workflow creates or updates a Salesforce Opportunity to keep your pipeline current. |
| **Admin record management** | Give your team an internal dashboard in Softr to look up, edit, or remove Salesforce records. Not every user needs a Salesforce license. |
| **Deduplication before outreach** | Before you create a record, query Salesforce with a SOQL filter. If the record exists, skip it or update it. |
| **Offboarding automation** | A user account is deleted in Softr. The workflow deletes or updates the matching Salesforce record. |
## Connect Softr to Salesforce
Salesforce needs a one-time package installation before you can connect your org through OAuth.

_Install the Softr app in your Salesforce org before you connect_
1. **Install the Softr app in your Salesforce org.** You do this once per org.
2. In Softr, open the **Workflows** section and create or edit a workflow.
3. Add a Salesforce action step (Create record, Update record, and so on).
4. Click **Connect Salesforce** and authorize Softr to access your Salesforce org through OAuth.
5. Select the **object type** you want to work with (Contact, Lead, Opportunity, Account, or a custom object).
6. Configure the action inputs. Map fields from your workflow data to the Salesforce object fields.
7. Publish your workflow to start syncing data.
---
# SharePoint integration
Source: https://docs.softr.io/workflows/integrations/sharepoint
Connect SharePoint with your Softr applications to put the sites your team already works in behind your no-code app. Turn form submissions into list items, keep request trackers current, upload member documents straight into the right document library, and publish pages and news posts — without anyone opening SharePoint to do it by hand.
## Overview
The Softr SharePoint integration lets your workflows work with three parts of a SharePoint site: **lists**, **document libraries**, and **pages**. Read and write list items to use SharePoint lists as a backend for trackers, registers, and intake logs; create folders, upload files, and browse libraries to keep documents organised as your app is used; and create, publish, and clean up site pages and news posts from a workflow.
Workflows can also run the other way round: a file arriving in a document library, a folder renamed, a list item edited, or a page published can be the thing that starts a workflow off.
Once you connect your Microsoft account, Softr reads your sites, lists, document libraries, pages, and list columns live. You pick them from dropdowns rather than typing IDs, and the column choices always reflect the list you selected — so a column added in SharePoint shows up in your workflow without any re-configuration.
## Available Actions
### List items
#### Find list items
Search a list and return the items you need. Filter by a single column value — for example every request whose `Status` is `Open` — or leave the filter blank to return the first items in the list. **Max items** caps how many come back (100 by default).
#### Get list item by ID
Fetch one item and use its column values in later steps. Identify it either by an item ID from an earlier step, or by a search condition — a column and value, which returns the first matching item.
#### Create list item
Add a new item to a list, setting the column values from your form fields, records, or earlier workflow steps.
#### Update list item
Change the column values on an existing item. As with **Get list item by ID**, you can point at the item by ID from a previous step, or find it by a column and value.
#### Delete list item
Remove an item from a list — again by ID from an earlier step, or by the first item matching a column and value.
#### Create list
Create a new list on a site, with a name and an optional description.
### Files & folders
#### Find file or folder
Search a document library by file or folder name — a partial name works. Scope the search to a single folder, or leave the folder blank to search the whole library. Returns up to **Max items** results (25 by default).
#### Get file or folder by ID
Fetch a single file or folder by its ID to use its details in later steps — name, path, link, size, and when it was created and last modified.
#### Get folder contents
List the files and folders inside a folder. Leave the folder blank to list the document library root. **Max items** caps the result (100 by default).
#### Upload file
Upload a file into a document library — for example a document a member submitted through a Softr form. Choose a destination folder or leave it blank to upload to the library root, optionally override the file name, and decide what happens if a file with that name already exists: **rename** the new file, **replace** the existing one, or **fail** the step.
#### Create folder
Create a folder in a document library — inside a parent folder, or at the library root. Same-name handling matches uploads: rename, replace, or fail.
#### Delete file or folder
Delete a file or folder from a document library by its ID.
### Pages
#### Create page
Create a new page on a site. **Title** is what readers see; **Page file name** is optional and becomes the last part of the page URL — leave it blank to derive it from the title, and `.aspx` is added for you if you omit it. Choose a **Page layout** (Article or Home), whether the result is an ordinary **Page** or a **News post**, and supply the **Content** as HTML, which is added as a single full-width text section.
The page is created as a **draft** — nobody else sees it until it is published, so follow this with **Publish page** when the page should go live immediately.
#### Get page by ID
Fetch a page from a site — picked from a dropdown of that site's pages — including its text content, URL, layout, page type, version, and whether it is currently published.
#### Publish page
Publish the latest version of a page, making it visible to everyone with access to the site. Pair it with **Create page** to publish in the same run, or use it on its own once a draft has been reviewed.
The action reports the page's real state after publishing rather than assuming success: if the page library has an approval flow, the page stays unpublished until that flow completes, and the result says so.
#### Delete page
Delete a page from a site, moving it to the site recycle bin. The result describes what was removed — file name, title, the URL it lived at, and whether it was published or still a draft.
## Available Triggers
Every SharePoint trigger checks the site on a schedule and starts your workflow once for each change it finds. Nothing that is already there when you turn the workflow on starts it — the first run is for what happens next.
### List items
#### List created
Starts a workflow when a new list is created on the site you pick — useful when teams spin up their own trackers and you want them announced, registered, or wired into your app without anyone remembering to say so.
#### List item created
Starts a workflow when a new item is added to the list you pick. Editing an item that is already there does not start it.
#### List item created or updated
Starts a workflow when an item is added to the list, and again whenever an existing item changes. Use the `changeType` field to tell the two apart.
### Files & folders
The three file triggers take an optional **File types** — a comma-separated list of extensions such as `pdf, docx` — so a workflow that only handles contracts is not woken by every image someone drops into the library. Leave it blank to watch every file type.
#### File added to folder
Starts a workflow once for each file added to the folder you pick; leave the folder blank to watch the document library root. Files added to a subfolder do not start it — use **File added to folder or subfolders** for those. Editing a file that is already there does not start it, and neither does a file moved in from somewhere else, because SharePoint keeps the date it was originally created. New folders never start it.
#### File added to folder or subfolders
The same trigger, widened: it starts once for each file added anywhere beneath the folder you pick, however deeply nested, including files added straight to that folder.
#### File created or updated
Starts a workflow when a file is added to the folder you pick, and again whenever a file already in it changes. Use the `changeType` field to tell the two apart. Subfolders are not included. Bear in mind SharePoint also counts renaming a file, checking it in or out, and restoring an earlier version as a change, so not every run means the contents differ — compare `modifiedAt` or `size` against what you saw last if that matters. Several edits between two checks arrive as a single run carrying the file's latest state.
#### Folder created or renamed
Starts a workflow once for each folder added directly to the folder you pick, and again whenever one of those folders is renamed. `changeType` tells the two apart, and a rename also gives you the old name in `previousName`, so you can find the folder in your own records. A folder created and renamed between two checks arrives as a single creation under its final name — there is no earlier name to report, because nobody had seen the folder before.
Folders created deeper down do not start it, and neither do files — pick one of the file triggers for those. A folder moved in from somewhere else does not start it either, because SharePoint keeps the date it was originally created; renaming it afterwards does. Deleting a folder never starts it, and neither does adding a file inside a folder you are watching, even though SharePoint updates that folder's modified date.
### Pages
#### Page created or updated
Starts a workflow for every page on the site you pick — a site keeps them all in one place, so there is nothing further to narrow it to. `changeType` tells a new page from a changed one.
Saving a draft counts as a change, as does editing the draft of a page that is already live, and publishing. Check `published` if your workflow should only act on what visitors can see, or `publishingLevel` if you are following the editing lifecycle — the two disagree for a live page that is currently checked out for editing. Several edits between two checks arrive as a single run carrying the page's latest state, so a long editing session does not start it once per keystroke. The page's content is not included: use **Get page by ID** with the ID from the trigger when you need the body.
## Key Benefits
- **Your SharePoint site as a backend:** Power Softr apps from the lists and libraries your team already maintains — no migration, no duplicate source of truth.
- **Always in sync with your site:** Sites, lists, libraries, pages, and columns are read live from SharePoint, so dropdowns never drift out of date when someone adds a column, a library, or a page.
- **Right value, right column type:** Filter values are matched against the column's real type — text, number, date, or yes/no — so filtering works the way it does inside SharePoint.
- **Work by ID or by condition:** Get, update, and delete items either by an ID carried from an earlier step or by a column value, so workflows work even when nothing upstream knows the item's ID.
- **Documents where they belong:** Files uploaded through your app land in the correct library and folder, with predictable handling when a name is already taken.
- **Both directions:** Write into SharePoint from your app, and start workflows from what happens on the site — a file arriving, a folder renamed, a list item edited, a page published.
- **Creations and changes, told apart:** Triggers that cover both label every run with `changeType`, and a renamed folder carries its old name, so a workflow can branch without keeping its own history.
- **Draft, then publish:** New pages start as drafts, so a workflow can assemble a page or news post and only make it visible once you are ready — in the same run or a later one.
## Example Use Cases
| Use Case | Description |
| :----------------------------------- | :--------------------------------------------------------------------------------------------------------------------- |
| **Form submissions to a list** | Capture every Softr form entry — requests, applications, incident reports — as a new item in a SharePoint list. |
| **Request tracker in a portal** | Find list items for the signed-in member and show them in your Softr app, then update the item when a status moves. |
| **Document intake** | Upload files members submit through your app straight into the right document library and folder. |
| **Per-client folders** | Create a folder for each new client record so their documents have a home from day one. |
| **Client-facing document list** | List a folder's contents, or search a library by name, to show clients only the documents that concern them. |
| **Clean-up after cancellation** | When a request is withdrawn, find the matching list item by reference and delete it, along with its uploaded files. |
| **Announcements from your app** | Publish a SharePoint news post when something happens in Softr — a release goes out, a policy changes, a client signs. |
| **Page per project or client** | Create a draft page from a template of your own HTML when a project starts, then publish it once someone reviews it. |
| **Retire outdated pages** | On a recurring schedule, get a page, check whether it is still current, and delete the ones that have gone stale. |
| **File lands, record follows** | When a file arrives in a watched library folder, create the matching record in your app and notify whoever owns it. |
| **Folder renames stay in step** | When a folder is created or renamed in a library, update the client record pointing at it so its links never go stale. |
| **Announce what the site publishes** | When a page on the site is published, post it to your app's news feed or email the members it concerns. |
## How to Connect Softr with SharePoint
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a SharePoint action, or start it with a SharePoint trigger.
3. Click **Connect SharePoint** and sign in with the Microsoft account that has access to the site you want to use.
4. Authorize Softr to access your SharePoint sites.
5. Pick the **Site**, then the **List**, **Document library**, or **Page** the action should work with.
6. Map fields from your Softr forms, records, or previous workflow steps to the list columns — or choose the file to upload, or write the page content.
7. Save and activate your workflow.
---
# Slack integration
Source: https://docs.softr.io/workflows/integrations/slack
Connect Slack with your Softr applications to automate updates, streamline team communication, and keep everyone aligned in real time. Build workflows that send notifications, post updates, and engage your team directly in Slack — all without code.

## Overview
The Softr Slack integration allows you to connect your no-code apps with your Slack workspace. Automatically send messages, alerts, and updates from your Softr app whenever key events occur, such as form submissions, user sign-ups, or data changes. Keep your team informed and responsive without manual effort.
With Softr, you can post messages to public or private Slack channels, or send direct messages to individual users based on triggers in your app — helping your team stay on top of what matters most.
## Available Actions
### Find Slack user
Find a Slack user by email address or by user ID to send targeted messages.
### Send direct message
Send a personalized message to a specific Slack user from your Softr app.
### Post channel message
Post automated messages to any public or private Slack channel, keeping your team updated in real time.
## Key Benefits
- **No-code simplicity:** Set up and manage your Slack workflows visually in Softr, without any technical setup.
- **Real-time communication:** Share critical updates instantly with your team in Slack.
- **Customizable automations:** Choose exactly which events in Softr trigger messages in Slack.
- **Team alignment:** Reduce context switching and keep communication centralized.
## Example Use Cases
| Use Case | Description |
| :-------------------------------- | :------------------------------------------------------------------------------ |
| **Form submission notifications** | Automatically post to a Slack channel whenever someone submits a form in Softr. |
| **New user onboarding** | Send a direct message to your onboarding team when a new user signs up. |
| **Project status updates** | Notify a specific channel when a record’s status changes. |
| **CRM and sales alerts** | Alert your sales team in Slack when deals are created or updated. |
## How to Connect Softr with Slack
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a Slack action.
3. Click **Connect to Slack** and authorize your Slack workspace.
4. Define triggers and customize your messages.
5. Save and activate your workflow.
---
# Stripe integration
Source: https://docs.softr.io/workflows/integrations/stripe
Connect Stripe with your Softr applications to take payments, manage customers, and run paid member portals — all from inside your no-code app. Build checkout flows on top of Softr forms, charge users on signup, distribute coupons to specific groups, and surface live billing data in admin dashboards.
## Overview
The Softr Stripe integration lets your app create and manage Stripe customers, kick off payments, look up charges, and pull live balance data — driven by the same forms, sign-ups, and record actions you already build with in Softr. Whether a member submits a checkout form, signs up for a paid tier, or an admin needs to issue a refund, the workflow runs end-to-end without leaving Softr.
This unlocks the patterns most Softr customers reach for first: paid member portals that charge on signup, client-facing checkout pages backed by a Softr form, internal admin tools for managing customers and payments, and finance dashboards that show charges and account balance in real time.
## Available Actions
### Customers
#### Create customer
Add a new customer to Stripe — typically from a Softr signup form, a checkout page, or a "new client" record action — capturing email, name, and any custom metadata you want to keep linked to the user.
#### Get customer
Look up a single Stripe customer by ID. Use this to surface a member's billing details inside their account page or in an admin record view.
#### List customers
Pull a list of customers from Stripe to power admin dashboards, member directories, or filtered views (for example, all customers created in the last 30 days).
#### Update customer
Keep Stripe in sync with your Softr app — update a customer's email, name, address, or metadata when the corresponding record changes in your data source.
#### Delete customer
Remove a customer from Stripe when they're deleted from your app or request account closure, keeping your billing data clean.
### Payment intents
#### Create payment intent
Start a new payment for a given amount and currency — the building block for charging members on signup, processing one-off purchases from a Softr form, or accepting payment on a custom checkout page.
#### Confirm payment intent
Confirm a payment intent to actually move the funds, completing the charge once the customer has provided their payment details.
### Charges
#### Get charge
Retrieve the details of a single charge by ID. Useful for displaying receipts, surfacing transaction details on a member's account page, or powering an admin "view payment" screen.
#### List charges
Fetch a list of charges from Stripe — by customer, by date range, or across the whole account — to feed transaction tables, revenue dashboards, or finance reports inside Softr.
#### Update charge
Update metadata or descriptions on an existing charge, for example to tag a payment with the related Softr record ID or attach internal notes.
### Coupons
#### Create coupon
Generate a new Stripe coupon — fixed amount or percentage off — directly from a Softr workflow. Perfect for spinning up promo codes for a campaign or rewarding specific user segments.
#### List coupons
Pull all available coupons from Stripe to display in a member portal, an admin discount manager, or a dropdown on your checkout form.
### Balance
#### Get balance
Fetch your current Stripe account balance, including available and pending funds, to power live finance dashboards for your team or owner-facing reports.
### Products
A **product** is the _what_ you sell — a membership tier, an event, a course, or a physical item. In Stripe, a product holds one or more **prices** (see below).
#### Create product
Add a catalog product to Stripe — set its name, description, images, and any metadata — for example when an admin publishes a new membership tier or event from a Softr form.
#### Get product
Look up a single product by ID to surface its details on a public product page or an admin edit screen.
#### Get many products
Retrieve a list of products, optionally filtered to only active or only archived ones, to power a catalog, an admin product manager, or a picker on a checkout form.
#### Update product
Update a product's mutable fields — name, description, images, default price, or metadata. Set the product to inactive to **archive** it (hide it from new purchases without affecting existing subscriptions).
#### Delete product
Permanently delete a product. Stripe only allows deleting a product that has never had a price attached; for the common case, use **Update product** and set it to inactive to archive instead.
### Prices
A **price** is the _how much / how often_ — `$10/month`, `$120/year`, or `$25 one-time`. One product can have many prices. Prices are largely immutable: to change an amount, create a new price and archive the old one.
#### Create price
Create a one-time or recurring price for a product. Set the amount (in the smallest currency unit — e.g. cents), currency, and, for recurring prices, the billing interval (day, week, month, or year) and interval count.
#### Get price
Retrieve a single price by ID — for example to show the amount and billing cadence on a checkout or account page.
#### Get many prices
List prices, optionally filtered to a single product, to power "show all price options for this membership / event" experiences on a native Softr page.
#### Archive price
Deactivate a price so it can no longer be used for new purchases (existing subscriptions on it are unaffected), or re-activate a previously archived price. This replaces a general "update price," which Stripe does not allow.
### Subscriptions
#### Create subscription
Subscribe a customer to one or more recurring prices — the core action for launching paid memberships. Optionally add a free trial, apply a coupon, or set the subscription to cancel at the end of the period.
#### Get subscription
Retrieve a single subscription by ID, including its status, items, and current period, to display on a member's account page.
#### Get many subscriptions
List subscriptions, filtered by customer, status, or price — for example to let a member see their own subscriptions or to power an admin churn dashboard.
#### Update subscription
Change a subscription: swap the price (upgrade / downgrade), change quantity, apply a coupon, update the payment method, or schedule cancellation at period end.
#### Cancel subscription
Cancel a subscription **immediately**. To let a member keep access until the end of the period they've already paid for — the more common membership flow — use **Update subscription** with _cancel at period end_ instead.
### Invoice items
#### Create invoice item
Add a one-off line item (a custom amount or an existing price) to a customer. Pending invoice items are automatically pulled into the customer's next invoice, or into a specific draft invoice — the first step of the manual invoicing flow.
### Invoices
Invoices follow Stripe's lifecycle: **draft → open → paid / uncollectible / void**.
#### Create invoice
Create a draft invoice for a customer. Pending invoice items are pulled in automatically. Choose whether Stripe charges the saved card automatically or emails the customer a payable invoice.
#### Get invoice
Retrieve a single invoice by ID, including its status, totals, and hosted invoice URL / PDF links.
#### Get many invoices
List invoices, filtered by customer, subscription, or status — for example to show a member their invoice history.
#### Finalize invoice
Move a draft invoice to **open**, locking its line items and generating the hosted invoice page and PDF. Required before an invoice can be paid or sent.
#### Pay invoice
Attempt to collect payment on an open invoice using the customer's default (or a specified) payment method.
#### Send invoice
Email an open invoice to the customer so they can pay via the hosted invoice page (for the "send invoice" collection method).
#### Void invoice
Void an open invoice that should not be paid. Voiding is final and cannot be undone.
## Key Benefits
- **No-code payments:** Take payments from your Softr app without writing backend code or stitching together a separate checkout tool.
- **Paid member portals:** Charge users on signup, gate content behind a successful payment, and manage subscribers inside Softr.
- **Real-time billing data:** Surface customers, charges, and account balance live inside your member views and admin dashboards.
- **End-to-end workflows:** Tie payments to the rest of your app — trigger emails, update records, notify your team, and provision access in the same workflow.
- **Customer data in sync:** Keep Stripe and your Softr database aligned automatically as users sign up, update their profile, or churn.
- **Recurring billing & memberships:** Build a catalog of products and prices, subscribe members to recurring plans, and let them upgrade, downgrade, or cancel — all from inside Softr.
- **Manual invoicing:** Assemble invoices from custom line items or subscriptions, then finalize, send, or collect payment as part of an automated workflow.
## Example Use Cases
| Use Case | Description |
| :-------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Charge on signup** | When a new member signs up to your Softr app, create a Stripe customer and a payment intent to charge them immediately. |
| **Form-based checkout** | Turn any Softr form into a checkout page — collect order details, create a payment intent, and confirm the charge in one workflow. |
| **Admin customer manager** | Build an internal tool where your team can search Stripe customers, view their charges, and update their details without leaving Softr. |
| **Live revenue dashboard** | Pull the current Stripe balance and a list of recent charges into a Softr dashboard so founders and ops teams can monitor revenue at a glance. |
| **Targeted coupon distribution** | Generate coupons on the fly and email them to a specific user group — VIPs, churning members, or campaign signups — straight from a workflow. |
| **Refund and receipt portal** | Let members look up their past charges from inside their account page, and let admins issue updates or annotate transactions internally. |
| **Sell memberships at multiple price points** | Publish a product with monthly and yearly prices, show both options on a Softr page, and subscribe the member to the price they pick. |
| **Self-serve subscription management** | Let members view their subscription, upgrade or downgrade the plan, or cancel at period end — without contacting support. |
| **Automated invoicing** | Add line items to a customer, create and finalize an invoice, then email it or charge it automatically — all triggered from a Softr record action. |
## How to Connect Softr with Stripe
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a Stripe action.
3. Click **Connect to Stripe** and paste your Secret API key.
4. Your Secret API key can be found in your Stripe Dashboard under **Developers → API keys**.
5. Pick the operation you need — create a customer, charge a payment, list charges, and so on.
6. Map fields from your Softr forms, records, or previous workflow steps to the Stripe action's inputs.
7. Save and activate your workflow.
---
# Supabase integration
Source: https://docs.softr.io/workflows/integrations/supabase
Connect Supabase with your Softr applications to read and write database records directly from your workflows — no SQL scripting required. Turn form submissions, sign-ups, and record changes into rows in your Supabase database, and pull that data back into your app in real time.
## Overview
The Softr Supabase integration lets your app create, find, update, and delete records in your Supabase database as part of a workflow. Trigger a new row from a form submission, update records when a status changes, or look up existing data to display or use in the next step — all driven by what your users do in Softr.
Whether you're building a customer portal, an internal admin tool, or a member dashboard, Supabase becomes the backend your Softr app writes to and reads from, so your existing database stays the single source of truth while Softr handles the front end and the automations. Supabase connects to your workflows through Softr's SQL / Database action, using your project's PostgreSQL credentials.
## Available Actions
### Find record
Look up the first record that matches your conditions — perfect for fetching a customer, order, or profile to display in your app or use in a later step.
### Find multiple records
Return every record that meets your criteria, so you can power a live list, dashboard, or digest from your Supabase data.
### Add record
Create a new record whenever a workflow runs — turn a form submission or sign-up into a row in your database instantly.
### Update record
Change a single record automatically as things happen in your app, such as updating a status or contact detail.
### Update multiple records
Update many records at once — ideal for bulk status changes or applying the same update across a set of rows.
### Delete record
Remove a single record that's no longer needed as work is cancelled or cleaned up.
### Delete multiple records
Clear out a batch of records at once to keep your database tidy.
## Key Benefits
- **No-code database access:** Read from and write to your Supabase database visually inside Softr — no SQL or backend code required.
- **Your data stays the source of truth:** Keep your existing Supabase backend and let Softr handle the front end and automations on top of it.
- **Always-current pickers:** Databases, schemas, tables, and fields load live from your connected project, so your options stay up to date.
- **Real-time two-way sync:** New submissions become rows the moment they arrive, and record changes flow back into your app instantly.
- **Custom queries when you need them:** Drop in a custom SQL query for anything the standard actions don't cover.
## Example Use Cases
| Use Case | Description |
| :------------------------------- | :------------------------------------------------------------------------------------------------------ |
| **Form-to-database intake** | A Softr form submission adds a new record to your Supabase table with all the submitted details. |
| **User provisioning on sign-up** | When a new member signs up, create their record in Supabase so their data is ready across your app. |
| **Status sync** | When a record moves to "In progress" in your Softr app, update the matching Supabase row automatically. |
| **Live data dashboard** | Use Find multiple records to power a Softr list block that always reflects your latest Supabase data. |
| **Bulk updates** | Update multiple records at once — for example, mark a batch of orders as shipped from an admin action. |
| **Automated cleanup** | Delete records that are cancelled or expired to keep your database tidy without manual work. |
## How to Connect Softr with Supabase
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a **SQL / Database** action — add, find, update, or delete a record.
3. Under **Account**, connect your Supabase database as a data source using your Supabase PostgreSQL (PSQL) credentials. See the [Supabase data source guide](/data-sources/supabase) for the exact steps. (Supabase is available on Professional plans and higher.)
4. Pick the **database**, **schema**, and **table** the action should work with.
5. Map fields from your Softr forms, records, or previous workflow steps to the action's inputs — or write a custom **SQL Query** for advanced cases.
6. Save and activate your workflow.
---
# Tally integration
Source: https://docs.softr.io/workflows/integrations/tally
Connect Tally with your Softr applications to put your form submissions to work automatically. Build workflows that fire the moment someone completes one of your Tally forms — then notify your team, create records, and sync the answers wherever they need to go, all without code.
## Overview
The Softr Tally integration lets you connect your no-code apps with Tally, the free-to-use form and survey builder. When a new submission is received on a form you choose, Softr starts a workflow and hands you the submitted answers — so you can route the data into the rest of your app and tools in real time.
With Softr, you can turn every Tally submission into action: save it to a Softr database, send a confirmation email, post a Slack message, create a CRM contact, or kick off any other workflow built on top of the response.
## Available Triggers
### New Submission
Fires when a new submission is received on the Tally form you select. The trigger payload includes a unique event ID you can use to deduplicate submissions, the form ID and name, the response and respondent IDs, the submission timestamp, a link to download the response as a PDF, and an `answers` object keyed by each question's label. Softr resolves the question labels and types for the form you pick — including text, email, phone, link, number, date, rating, single- and multiple-choice, ranking, and file upload answers — and turns multiple-choice selections into their readable labels, so you can reference each answer directly in later workflow steps.
## Key Benefits
- **No-code form automation:** Connect a Tally form and act on every submission visually in Softr — no webhooks to wire up by hand.
- **Instant reactions:** Workflows fire the moment a form is submitted — no polling, no delay.
- **Readable answers:** Multiple-choice and dropdown selections come through as their labels, not internal IDs, so your workflows stay easy to read and map.
- **Works with any form:** Pick any published form on your Tally account, including multiple-choice questions and file uploads.
- **Secure connection:** Authorize once with OAuth — no API keys to copy or rotate.
## Example Use Cases
| Use Case | Description |
| :----------------------------- | :----------------------------------------------------------------------------------------------- |
| **Submissions to a database** | Save every Tally response to a Softr database to power a list, portal, or admin dashboard. |
| **Lead routing to CRM** | Create or update a contact in HubSpot, Salesforce, or Xero when a lead form is submitted. |
| **Instant team notifications** | Post new submissions to a Slack channel or send an email so the right person responds fast. |
| **Application intake** | Kick off an onboarding or review workflow whenever an application or registration form comes in. |
| **File collection** | Capture uploaded files from a submission and archive their URLs to a database or storage tool. |
| **Confirmation follow-ups** | Send a personalized confirmation email to the submitter using the answers from their submission. |
## How to Connect Softr with Tally
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add the Tally **New Submission** trigger.
3. Click **Connect Tally** and authorize Softr to access your Tally account.
4. Pick the **form** you want to watch for new submissions.
5. Map the submission's answers to the inputs of your downstream actions (database records, emails, Slack messages, and more).
6. Save and activate your workflow — Softr registers the webhook with Tally automatically.
---
# Telegram integration
Source: https://docs.softr.io/workflows/integrations/telegram
Connect Telegram with your Softr applications to broadcast updates, alert your team in real time, and keep your community engaged — all powered by a Telegram bot you control. Build workflows that send messages, photos, videos, documents, and polls directly from your Softr app, without writing a single line of code.
## Overview
The Softr Telegram integration lets your no-code app push messages and media into any Telegram chat, group, or channel through your own bot. Whenever something happens in your app — a form is submitted, a member signs up, a record changes status — you can deliver an instant notification, a rich media update, or a poll to the right audience on Telegram.
This fits naturally into customer portals, member communities, and internal ops dashboards. Use it to alert your team in a private group when a high-priority lead comes in, to broadcast announcements to subscribers in a public channel, to share files and reports with clients, or to gather quick feedback from your community with a poll.
## Available Actions
### Send message
Send a text message to any Telegram chat, group, or channel. Perfect for instant alerts, confirmations, and announcements triggered by events in your Softr app.
### Send photo
Deliver an image to a chat with an optional caption. Use it to share screenshots, product shots, charts, or any visual update straight from your workflow.
### Send video
Send a video file to your audience on Telegram. Great for sharing tutorials, demos, or recorded updates with members and teams.
### Send document
Attach and send a file — PDFs, spreadsheets, contracts, or reports — to keep clients, members, and teammates in the loop without leaving Telegram.
### Send poll
Post a poll to a chat or channel to collect quick feedback from your community, run a vote, or check in with your team on a decision.
### Get chat
Retrieve information about a Telegram chat, group, or channel — useful for confirming a destination exists or pulling chat details into your workflow before sending.
## Key Benefits
- **No-code simplicity:** Wire up Telegram to your Softr app visually, with no scripting or server setup.
- **Reach members where they are:** Telegram is already where many communities, teams, and customers spend their day — meet them there instead of in another inbox.
- **Rich media, not just text:** Send photos, videos, files, and polls — not just plain messages — to make updates more engaging.
- **Real-time ops alerts:** Notify the right group the moment something happens in your app, so nothing slips through the cracks.
- **One bot, many workflows:** Connect once with your bot token and reuse it across every Telegram action in every workflow.
## Example Use Cases
| Use Case | Description |
| :---------------------------------- | :--------------------------------------------------------------------------------------------------------------------- |
| **New lead alerts** | Post to your sales team's private Telegram group every time a prospect submits the contact form on your Softr site. |
| **Member community broadcasts** | Announce new content, events, or product drops to a Telegram channel whenever a record is published in your Softr app. |
| **Order and booking confirmations** | Send a confirmation message — with an attached PDF invoice or receipt — to a customer's Telegram chat after checkout. |
| **Internal ops alerts** | Notify your operations team when a record's status changes, an inventory item runs low, or a workflow fails. |
| **Customer support escalations** | Ping your support group with a screenshot or document the moment a high-priority ticket is created. |
| **Community polls and feedback** | Launch a quick poll in your members-only Telegram channel to gather opinions on upcoming features or events. |
## How to Connect Softr with Telegram
1. In Telegram, start a chat with **@BotFather** and send the `/newbot` command. Pick a name and username for your bot, then copy the **bot token** BotFather gives you. Add your bot to the chat, group, or channel you want to send messages to, and give it permission to post.
2. Open your Softr app and go to **Workflows**.
3. Create a new workflow and add a Telegram action.
4. Click **Connect to Telegram** and paste your bot token.
5. Choose the chat or channel ID, and map your message, media, or poll content from forms, records, or previous workflow steps.
6. Save and activate your workflow.
---
# TinyURL integration
Source: https://docs.softr.io/workflows/integrations/tinyurl
Connect TinyURL with your Softr applications to turn long, unwieldy URLs into short, shareable links automatically. Build workflows that shorten links the moment they're needed — when a form is submitted, a record is added, or a new member signs up — so every link you share is clean and easy to pass along.
## Overview
The Softr TinyURL integration links your no-code apps directly to your TinyURL account. Whenever your workflow produces a URL worth sharing — a referral link, a campaign page, a personalized signup link — you can automatically shorten it into a TinyURL link with a custom alias, your choice of short domain, and optional tags and expiration, then store or send the short link anywhere in your app.
Whether you're building a marketing dashboard, a member portal, or a referral program, the TinyURL integration keeps every shared link short, readable, and on-message — powered by one of the longest-running URL shorteners on the web.
## Available Actions
### Create link
Shorten any URL into a TinyURL link with an optional custom alias, short domain (tinyurl.com, tiny.one, or rotf.lol), tags, expiration date, and description — all set dynamically from your Softr workflow. The short link comes back ready to store in a record, send in an email, or show to your users.
### Update link
Change a link's metadata — move it to another domain, rename its alias, replace its tags or description, set a new expiration date, or toggle click-analytics collection. Pick the link from a live dropdown of the aliases in your connected TinyURL account.
### Change destination
Point an existing short link at a new destination URL, so links you've already shared start leading somewhere new — perfect for rotating promos behind one permanent short link. Available on paid TinyURL plans.
### Archive link
Deactivate a link and move it to your archived list when a campaign ends or a link shouldn't be used anymore — reversible from your TinyURL dashboard.
### List links
Retrieve the links in your connected TinyURL account — active or archived — to loop over them, sync them into a Softr table, or build reports.
## Key Benefits
- **No-code simplicity:** Configure TinyURL actions visually in Softr — no code required beyond the one-time API token setup.
- **Short links on autopilot:** Shorten URLs the moment your workflow runs, instead of pasting them into TinyURL by hand.
- **Readable, memorable links:** Give each link a custom alias like `tinyurl.com/spring-sale` instead of a random code.
- **Links that expire when you want:** Set an expiration date on time-limited links — promos, invitations, early-access offers — so they stop working on schedule.
- **Share-ready output:** Use the short link immediately in the next workflow step — save it to a record, send it via email or Slack, or display it in your app.
## Example Use Cases
| Use Case | Description |
| :------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------ |
| **Referral link generator** | Create a personalized short link for each new member who signs up to your Softr app, and save it to their profile. |
| **Campaign link intake** | Let your marketing team submit long campaign URLs through a Softr form that returns a short, tagged TinyURL link. |
| **Record-based link shortening** | Shorten the URL field of every new record — listings, articles, products — and store the short link alongside it. |
| **Time-limited promotions** | Generate a short promo link with an expiration date whenever a new offer is added, so expired campaigns stop resolving automatically. |
| **Event promotion** | When a new event is added in your Softr app, generate a short registration link ready for social media and email. |
| **Document sharing** | Shorten long file or page URLs before emailing them to clients, so messages stay clean and easy to read. |
## How to Connect Softr with TinyURL
1. Open your Softr workspace and go to **Workflows**.
2. Create a new workflow or open an existing one, then add a TinyURL action.
3. In the **Account** field, click **Add another account** and paste your TinyURL **API token**.
4. To create an API token, open TinyURL and go to **Account → Settings → API**, then generate a new token.
5. Click **Save** — Softr verifies your token and connects the account.
6. Map the **Destination URL** from your Softr forms, records, or previous workflow steps, optionally pick a domain and add an alias, tags, or an expiration date, then activate your workflow.
---
# Trello integration
Source: https://docs.softr.io/workflows/integrations/trello
Connect Trello with your Softr applications to turn form submissions, sign-ups, and record changes into Trello cards automatically — no code required.
## Overview
The Softr Trello integration links your no-code apps to your Trello boards. When something happens in your app — a form is submitted, a member signs up, a record is updated — Softr can create a Trello card on the right list, assign members, apply labels, and set a due date, keeping your team's board in sync without manual data entry.
Whether you're running an intake pipeline, a support queue, or a content calendar, you can wire Softr forms and record actions straight into Trello so work lands where your team already tracks it.
## Available Actions
### Card: Create
Create a new card on any Trello list. Set the card name and description, place it at the top or bottom of the list, assign board members, apply labels, and set start and due dates — all mapped from your Softr form fields, records, or earlier workflow steps. Boards, lists, members, and labels are loaded live from your connected account, so you always pick from real, up-to-date options.
### Card: Get
Look up a single card by its ID and pull its details — name, description, list, due date, members, and labels — into your workflow to use in later steps.
### Card: Update
Change an existing card: rename it, edit the description, move it to another list or board, update members, labels, position, and dates, or archive and restore it. Only the fields you set are changed.
### Card: Delete
Permanently delete a card by its ID. To keep the card but hide it, use Card: Update to archive it instead.
### Card: List
Return all cards in a chosen list — perfect for building dashboards, digests, or driving follow-up steps for each card in a list.
## Key Benefits
- **No-code simplicity:** Configure the Trello action visually in the Softr workflow builder — no scripting required.
- **Live board data:** Boards, lists, members, and labels are fetched from your connected Trello account so dropdowns stay current.
- **Right card, right place:** Send each card to the exact list and position, with members, labels, and due dates set automatically.
- **Real-time sync:** Cards appear on your board the moment the triggering event happens in your Softr app.
## Example Use Cases
| Use Case | Description |
| :--------------------- | :------------------------------------------------------------------------------------------------------------------- |
| **Form-to-card** | A Softr form submission creates a Trello card on your intake list with the submission details in the description. |
| **Support queue** | When a customer submits a request through your portal, create a card on the "New" list and assign the on-duty agent. |
| **Content calendar** | A new record in your Softr content database creates a card with a due date so writers see deadlines on the board. |
| **Sign-up onboarding** | When a new member signs up, create a Trello card to kick off your onboarding checklist for that customer. |
## How to Connect Softr with Trello
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add the **Trello** action (Card: Create).
3. Click **Connect to Trello**. Generate an API key at [trello.com/power-ups/admin](https://trello.com/power-ups/admin), then use the token link on that page to generate an API token, and paste both into Softr.
4. Choose the **board** the card should be created on.
5. Pick the **list** and map your Softr form fields, records, or previous steps to the card's name, description, members, labels, and dates.
6. Save and activate your workflow.
---
# Twilio integration
Source: https://docs.softr.io/workflows/integrations/twilio
Connect Twilio with your Softr applications to send SMS messages straight from your no-code app. Confirm bookings, send reminders, alert your team, and keep customers in the loop — all triggered automatically by what happens inside Softr.
## Overview
The Softr Twilio integration lets you turn any event in your app into a text message. Send SMS confirmations after a form submission, push real-time alerts to your operations team, or notify members the moment a record changes — without touching code.
Whether you're running a booking app, a customer portal, or an internal ops dashboard, Twilio gives your Softr workflows a direct line to your users' phones for the moments that matter most.
## Available Actions
### Send SMS
Send a text message to any phone number using your Twilio account. Personalize the message with data from your Softr forms, records, or earlier workflow steps.
## Key Benefits
- **No-code simplicity:** Add SMS to any Softr workflow without writing code or wiring up APIs.
- **Reach customers instantly:** Texts get opened in seconds — perfect for confirmations, reminders, and time-sensitive alerts.
- **Personalized at scale:** Pull names, dates, order details, and any other field from your Softr app straight into the message body.
- **Reliable global delivery:** Lean on Twilio's carrier network to send messages to customers and team members anywhere in the world.
- **Trigger-based automation:** Fire texts off form submissions, sign-ups, status changes, or scheduled workflows — fully automated.
## Example Use Cases
| Use Case | Description |
| :--------------------------------- | :-------------------------------------------------------------------------------------------------------- |
| **Booking confirmations** | Text customers a confirmation with their date, time, and reference as soon as they submit a booking form. |
| **Appointment reminders** | Send a reminder SMS the day before a scheduled appointment to cut no-shows. |
| **Order and payment receipts** | Notify customers their order has been placed or their payment has gone through. |
| **Urgent ops alerts** | Page your on-call team with an SMS when a high-priority ticket, lead, or issue lands in Softr. |
| **Member account notifications** | Welcome new members or send verification-style alerts when sensitive account changes happen. |
| **Deadline and renewal reminders** | Text customers ahead of subscription renewals, document deadlines, or expiring offers. |
## How to Connect Softr with Twilio
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add the **Send SMS** Twilio action.
3. Click **Connect to Twilio** and paste in your Account SID, Auth Token, and sender phone number.
4. Your Account SID, Auth Token, and sender phone number can be found in your Twilio Console.
5. Pick the trigger that should fire it — a form submission, record update, or scheduled run.
6. Write your message and map fields from your Softr forms or records into the recipient number and message body.
7. Save and activate your workflow.
---
# Typeform integration
Source: https://docs.softr.io/workflows/integrations/typeform
Connect Typeform with your Softr applications to put your form submissions to work automatically. Build workflows that fire the moment someone submits one of your Typeform forms — then notify your team, create records, and sync the answers wherever they need to go, all without code.
## Overview
The Softr Typeform integration lets you connect your no-code apps with Typeform, the online form and survey builder. When a new submission is received on a form you choose, Softr starts a workflow and hands you the submitted answers — so you can route the data into the rest of your app and tools.
With Softr, you can turn every Typeform submission into action: save it to a Softr database, send a confirmation email, post a Slack message, create a CRM contact, or kick off any other workflow built on top of the response.
## Available Triggers
### New Submission
Fires when a new response is received on the Typeform form you select. The trigger payload includes the response token (a unique ID you can use to deduplicate submissions), the submission and landed timestamps, any hidden fields passed to the form, and an `answers` object keyed by each question's title. Softr resolves the question titles and types for the form you pick — including text, email, number, date, yes/no, single- and multiple-choice, and file upload URL answers — so you can reference each answer directly in later workflow steps.
## Key Benefits
- **No-code form automation:** Connect a Typeform form and act on every submission visually in Softr — no webhooks to wire up by hand.
- **Instant reactions:** Workflows fire the moment a form is submitted — no polling, no delay.
- **Works with any form:** Pick any form on your Typeform account, including hidden fields, file uploads, and multiple-choice questions.
- **Secure connection:** Authorize once with OAuth — no API keys to copy or rotate.
## Example Use Cases
| Use Case | Description |
| :----------------------------- | :----------------------------------------------------------------------------------------------- |
| **Submissions to a database** | Save every Typeform response to a Softr database to power a list, portal, or admin dashboard. |
| **Lead routing to CRM** | Create or update a contact in HubSpot, Salesforce, or Xero when a lead form is submitted. |
| **Instant team notifications** | Post new submissions to a Slack channel or send an email so the right person responds fast. |
| **Application intake** | Kick off an onboarding or review workflow whenever an application or registration form comes in. |
| **File collection** | Capture uploaded files from a submission and archive their URLs to a database or storage tool. |
| **Confirmation follow-ups** | Send a personalized confirmation email to the submitter using the answers from their submission. |
## How to Connect Softr with Typeform
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add the Typeform **New Submission** trigger.
3. Click **Connect Typeform** and authorize Softr to access your Typeform account.
4. Pick the **form** you want to watch for new submissions.
5. Map the submission's answers to the inputs of your downstream actions (database records, emails, Slack messages, and more).
6. Save and activate your workflow — Softr registers the webhook with Typeform automatically.
---
# Xano integration
Source: https://docs.softr.io/workflows/integrations/xano
Connect Xano with your Softr applications to read and write database records directly from your workflows — no SQL scripting required. Turn form submissions, sign-ups, and record changes into records in your Xano backend, and pull that data back into your app in real time.
## Overview
The Softr Xano integration lets your app create, find, update, and delete records in your Xano database as part of a workflow. Trigger a new record from a form submission, update records when a status changes, or look up existing data to display or use in the next step — all driven by what your users do in Softr.
Whether you're building a customer portal, an internal admin tool, or a member dashboard, Xano becomes the backend your Softr app writes to and reads from, so your existing backend stays the single source of truth while Softr handles the front end and the automations. Xano connects to your workflows through Softr's SQL / Database action, using Xano's Data Connector.
## Available Actions
### Find record
Look up the first record that matches your conditions — perfect for fetching a customer, order, or profile to display in your app or use in a later step.
### Find multiple records
Return every record that meets your criteria, so you can power a live list, dashboard, or digest from your Xano data.
### Add record
Create a new record whenever a workflow runs — turn a form submission or sign-up into a record in your database instantly.
### Update record
Change a single record automatically as things happen in your app, such as updating a status or contact detail.
### Update multiple records
Update many records at once — ideal for bulk status changes or applying the same update across a set of records.
### Delete record
Remove a single record that's no longer needed as work is cancelled or cleaned up.
### Delete multiple records
Clear out a batch of records at once to keep your database tidy.
## Key Benefits
- **No-code database access:** Read from and write to your Xano backend visually inside Softr — no SQL or backend code required.
- **Your data stays the source of truth:** Keep your existing Xano backend and let Softr handle the front end and automations on top of it.
- **Always-current pickers:** Databases, schemas, tables, and fields load live from your connected instance, so your options stay up to date.
- **Real-time two-way sync:** New submissions become records the moment they arrive, and record changes flow back into your app instantly.
- **Custom queries when you need them:** Drop in a custom SQL query for anything the standard actions don't cover.
## Example Use Cases
| Use Case | Description |
| :------------------------------- | :----------------------------------------------------------------------------------------------------- |
| **Form-to-database intake** | A Softr form submission adds a new record to your Xano table with all the submitted details. |
| **User provisioning on sign-up** | When a new member signs up, create their record in Xano so their data is ready across your app. |
| **Status sync** | When a record moves to "In progress" in your Softr app, update the matching Xano record automatically. |
| **Live data dashboard** | Use Find multiple records to power a Softr list block that always reflects your latest Xano data. |
| **Bulk updates** | Update multiple records at once — for example, mark a batch of orders as shipped from an admin action. |
| **Automated cleanup** | Delete records that are cancelled or expired to keep your database tidy without manual work. |
## How to Connect Softr with Xano
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a **SQL / Database** action — add, find, update, or delete a record.
3. Under **Account**, connect your Xano database as a data source. First enable the **Data Connector** add-on in Xano, then connect your instance in Softr. See the [Xano data source guide](/data-sources/xano) for the exact steps.
4. Pick the **database**, **schema**, and **table** the action should work with.
5. Map fields from your Softr forms, records, or previous workflow steps to the action's inputs — or write a custom **SQL Query** for advanced cases.
6. Save and activate your workflow.
---
# Xero integration
Source: https://docs.softr.io/workflows/integrations/xero
Connect Xero with your Softr applications to automate your accounting busywork — create invoices and contacts the moment something happens in your app, look up financial records on demand, and react instantly when invoices or customers change in Xero. Build billing and CRM-style workflows on top of your live accounting data, all without code.
## Overview
The Softr Xero integration lets you connect your no-code apps with your Xero organization. Create and update contacts (customers and suppliers) and sales invoices or bills, fetch a single record by ID, or pull a page of contacts and invoices to display and act on inside Softr. Every action returns the created or updated record so you can use it in any downstream workflow step.
With Softr, you can turn a form submission into a Xero contact, raise an invoice when a deal is marked won, surface outstanding invoices in a member portal, and kick off follow-up automations the moment a contact or invoice changes in Xero — keeping your app and your books in sync both ways.
## Available Actions
### Create contact
Create a new contact (customer or supplier) in your Xero organization, for example when someone signs up or submits a form in your Softr app.
### Update contact
Update an existing Xero contact — refresh their details, addresses, or status when records change in Softr.
### Get contact
Fetch a single contact by ID so you can display or reuse their details in a later workflow step.
### List contacts
Retrieve a page of contacts from your organization to show in a list block, sync to a Softr database, or loop over in a workflow.
### Create invoice
Create a new sales invoice (ACCREC) or bill (ACCPAY), including line items, due date, currency, branding theme, and status — for example, billing a customer automatically after a booking or order.
### Update invoice
Update an existing invoice to change its line items, status, dates, or reference as records change in your app.
### Get invoice
Fetch a single invoice by ID or invoice number to read its amount, status, and details downstream.
### List invoices
Retrieve a page of invoices — for example, to surface outstanding or paid invoices to members or to drive a reminder workflow.
## Available Triggers
### Resource changed
Fires when a contact, invoice, or credit note is created or updated in Xero. Choose which resource to listen to and, optionally, limit it to create or update events only. Use it to keep Softr records in sync with your books and to start follow-up automations the moment something changes in Xero.
## Key Benefits
- **No-code accounting automation:** Configure Xero actions and triggers visually in Softr — no API setup, no scripts.
- **Two-way sync:** Push contacts and invoices into Xero and react to changes coming back out, so your app and your books stay aligned.
- **Live financial data in your app:** Pull contacts and invoices into list and detail blocks to build billing portals and finance dashboards.
- **Multi-organization ready:** Pick which Xero organization each action uses, so agencies and multi-entity businesses can automate every set of books.
- **Reusable outputs:** Every action returns the full record, ready to drop into emails, database records, Slack messages, or any other workflow step.
## Example Use Cases
| Use Case | Description |
| :------------------------------ | :------------------------------------------------------------------------------------------------ |
| **New customer to Xero** | Create a Xero contact automatically when someone signs up or submits a form in your Softr app. |
| **Invoice on order or booking** | Raise a sales invoice when a customer places an order or confirms a booking, then email the link. |
| **Billing portal** | Use **List invoices** to show members their outstanding and paid invoices inside a Softr portal. |
| **Keep CRM contacts in sync** | Update a Xero contact whenever the matching record changes in your Softr database. |
| **Payment follow-ups** | Trigger on a changed invoice and send a reminder or update a record when its status changes. |
| **Finance dashboard** | Pull contacts and invoices into a Softr admin dashboard for a real-time view of your accounts. |
## How to Connect Softr with Xero
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a Xero action (or the **Resource changed** trigger).
3. Click **Connect to Xero** and sign in with your Xero account, then review and authorize the requested permissions.
4. Select the **Organization** you want the action or trigger to use (Softr supports connecting more than one Xero organization).
5. Map fields from your Softr forms, records, or previous workflow steps to the action's inputs (for example, contact details or invoice line items).
6. Save and activate your workflow.
---
# Zendesk integration
Source: https://docs.softr.io/workflows/integrations/zendesk
Connect Zendesk with your Softr applications to automate support operations and eliminate manual ticket work. Build workflows that create and update tickets, log comments, and look up users and organizations — all triggered by events in your Softr app.
## Overview
The Softr Zendesk integration links your no-code apps directly to your Zendesk support account. Whenever something happens in Softr — a form submission, a record status change, a new user sign-up — you can automatically create tickets, update their details, post comments, or retrieve customer and organization data to drive the next step in your workflow.
Whether you're building a client portal, an internal help desk tool, or an operations dashboard, the Zendesk integration removes the gap between what's happening in your Softr app and what your support team sees in Zendesk.
## Available Actions
### Create ticket
Open a new support ticket in Zendesk with a subject, description, priority, assignee, and tags — all set dynamically from your Softr workflow.
### Get ticket
Retrieve the full details of a specific ticket by its ID, so you can use ticket data in later workflow steps.
### Update ticket
Change a ticket's status, priority, assignee, group, or tags to keep Zendesk in sync with what's happening in your Softr app.
### Delete ticket
Remove a ticket from your Zendesk queue — useful for cleanup workflows or voided requests.
### List tickets
Fetch a filtered list of tickets by status, group, organization, or Zendesk search query to power reports, dashboards, or conditional logic.
### Add comment to ticket
Post a public reply or internal agent note to any ticket — ideal for logging Softr form responses or escalation details directly inside Zendesk.
### Get user
Look up a Zendesk user by ID to retrieve their name, email, role, and organization for use in downstream workflow steps.
### List users
Search and return a set of Zendesk users based on any query criteria, such as role or organization.
### Get organization
Retrieve the full details of a Zendesk organization by ID, including domain names, notes, and tags.
### List organizations
Search and return a list of Zendesk organizations to drive lookups, filters, or conditional branching in your workflow.
## Key Benefits
- **No-code simplicity:** Configure every Zendesk action visually in Softr — no coding required beyond the initial API token setup.
- **Instant ticket creation:** Turn any Softr form submission or record event into a Zendesk ticket automatically, the moment it happens.
- **Full ticket lifecycle:** Create, update, comment on, and close tickets without leaving your workflow canvas.
- **Richer automation with lookups:** Pull user and organization data mid-workflow to personalize messages, route tickets, or update other systems.
- **Support-ready portals:** Build client-facing forms and internal help desks in Softr that feed directly into Zendesk — giving your support team everything they need, where they already work.
## Example Use Cases
| Use Case | Description |
| :----------------------------- | :------------------------------------------------------------------------------------------------------------------------------ |
| **Support request form** | Create a Zendesk ticket automatically when a user submits a help request form in your Softr portal. |
| **Status sync** | Update the linked Zendesk ticket to `solved` when a record's status field changes to "Resolved" in your Softr database. |
| **Agent notes from forms** | Post an internal note to a ticket when a customer fills in a follow-up form, keeping all context in one place. |
| **Escalation alerts** | When a high-priority record is flagged in Softr, create an urgent Zendesk ticket and notify your team in Slack. |
| **Client portal ticket feed** | Display a filtered list of open tickets for each logged-in user by querying Zendesk with their email inside a Softr list block. |
| **New user onboarding ticket** | Auto-create a welcome or setup ticket in Zendesk when a new member signs up to your Softr app. |
## How to Connect Softr with Zendesk
1. Open your Softr workspace and go to **Workflows**.
2. Create a new workflow or open an existing one, then add a Zendesk action.
3. In the **Account** field, click **Add another account** and enter your Zendesk **subdomain**, **email address**, and **API token**.
4. To generate an API token, log into Zendesk and go to **Admin Center → Apps & Integrations → Zendesk API → API Tokens**, then click **Add API token**.
5. Click **Save** — Softr verifies your credentials and connects the account.
6. Configure the action inputs, click **Continue**, and activate your workflow.
---
# Zoho CRM
Source: https://docs.softr.io/workflows/integrations/zoho-crm
# Zoho CRM integration
Connect Zoho CRM with your Softr applications to capture leads, keep contacts current, and move deals forward automatically. Push data from your forms and portals into Zoho CRM, pull records back into your app, or start a workflow the moment a record is created, updated, or deleted in the CRM — all without writing code.
## Overview
The Softr Zoho CRM integration links your no-code app to your Zoho CRM organization so records stay in sync on both sides. When someone signs up, submits a form, or updates a record in Softr, your workflow can create, update, or look up records in the Leads, Contacts, Accounts, and Deals modules.
Every action works across those four modules and includes your custom fields, so you can build lead capture sites, customer portals, and internal sales tools on top of the CRM your team already uses. Triggers work the other way round: when a record is created, updated, or deleted in one of those modules, Zoho notifies Softr instantly and your workflow runs.
## Available Actions
### Create record
Add a new record to the Leads, Contacts, Accounts, or Deals module. Pick the module, then map values from your Softr form, record, or an earlier workflow step onto the module fields, including custom fields.
### Update record
Change an existing record by ID. Fields you leave out keep their current values, so you can update a single phone number or deal stage without touching the rest of the record.
### Create or update record
Create a record, or update the matching one if it already exists. Zoho matches on each module's own duplicate-check field — Email for Leads and Contacts, Account Name for Accounts, and Deal Name for Deals. Include that field in your values so Zoho can find the match.
### Get record
Retrieve one record by ID with every field the module defines. Use it to show a member their own CRM record, or to read current values before you decide what to do next.
### List records
List records from a module. Zoho requires an explicit field selection, so you choose which fields come back. You can also set the page size (up to 200), sort by any field in ascending or descending order, and page through results with the page token from the previous run.
### Search records
Find records in a module with the same condition builder the other look-up actions use. The field list comes from the module's own schema, so your custom fields are there to filter on and a field the module does not have cannot be asked for. Set the page size (up to 200) and page through the results by page number.
Zoho's search is a single flat chain of comparisons, which sets a few limits. One filter uses either **all** or **any**, not both, and holds at most 10 comparisons — "is none of" and conditions on dates each expand to more than one. "Is any of" matches up to 100 values. The conditions that translate are is, is not, starts with, greater or less than (or equal to), is between, is not between, is any of, is all of and is none of; contains, ends with and is empty have no equivalent in Zoho's search. Anything Zoho cannot express is reported before the search runs, naming the condition at fault, and Zoho's own message is shown when it rejects a request.
On date and date-time fields a condition covers whole days, so "is" on a date matches every record from that day rather than one exact timestamp, and relative ranges such as the last 7 days resolve when the workflow runs.
## Available Triggers
Zoho CRM triggers are **Instant**: Zoho notifies Softr as soon as a record changes, and the workflow runs right away. Each trigger watches one module — Leads, Contacts, Accounts, or Deals.
### Record created
Starts a workflow when a record is created in the selected module. The output carries the record ID; chain **Get record** to read its fields.
### Record updated
Starts a workflow when a record in the selected module is edited. The output carries the record ID, the names of the fields that changed, and their new values, so a workflow can branch on what changed without an extra call. Only edits to the record itself count — adding a note or changing a related record does not fire this trigger.
### Record deleted
Starts a workflow when a record is deleted from the selected module. The output carries the ID of the deleted record.
Every trigger run is about a single record. When many records change at once — a bulk edit or an import — Softr starts one workflow run per record. Softr registers the notification with Zoho when you turn the workflow on, keeps it active for as long as the workflow stays on, and removes it when you turn the workflow off.
## Key Benefits
- **No-code CRM automation:** Set up Zoho CRM steps visually in the Softr workflow builder — no developer and no third-party automation tool needed.
- **Works with your custom fields:** Field pickers load live from your Zoho CRM organization, so custom fields are available next to the standard ones.
- **Two-way data flow:** Write new records into Zoho CRM and read existing ones back into your app from the same workflow.
- **Real-time:** Changes in Zoho CRM start your workflows the moment they happen — no polling and no delay.
- **No duplicates:** Use Create or update record, or search first, so repeat form submissions update the right record instead of creating a second one.
- **Built for portals:** Give members a branded Softr experience while your team keeps working in Zoho CRM.
- **Multi-step workflows:** Chain Zoho CRM actions with other integrations — post to Slack after a new lead, or send an email after a deal changes.
## Example Use Cases
| Use Case | Description |
| :------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------- |
| **Lead capture from forms** | When a visitor submits a form in your Softr app, create a Lead in Zoho CRM with their details and source. |
| **Member sign-up sync** | When a new user signs up to your portal, create or update the matching Contact so the CRM always has the current record. |
| **Self-serve customer portal** | Let members view and edit their own Contact record from inside your Softr app. |
| **Deal pipeline updates** | When a status changes in Softr, update the linked Deal so your pipeline stays current. |
| **Duplicate check before outreach** | Search for a matching record by email, name, or any other field before you create one, then update the existing record instead of adding a copy. |
| **Internal sales dashboard** | List Deals or Accounts from Zoho CRM in a Softr table, and let your team update them without a full CRM seat. |
| **Account enrichment** | Get a record by ID mid-workflow to read current field values, then branch on them in later steps. |
| **React to CRM changes** | When a Lead is created or a Deal is updated in Zoho CRM, notify your team in Slack or update the matching record in your Softr database. |
| **Act on a stage change** | When a Deal is updated, check whether the stage is among the changed fields and start the hand-off workflow only when it is. |
| **Keep your app in sync on deletion** | When a record is deleted in Zoho CRM, remove or archive the matching record in your Softr app. |
## How to Connect Softr with Zoho CRM
1. Open your Softr app and go to **Workflows**.
2. Create a new workflow and add a Zoho CRM trigger, such as Record updated, or a Zoho CRM action, such as Create record.
3. Click **Connect** and sign in to Zoho to give Softr permission to access your Zoho CRM account.
4. Select the **Module** you want to work with — Leads, Contacts, Accounts, or Deals.
5. Configure the inputs — for an action, map your workflow data to the module fields, or set the record ID, filters, and sorting.
6. Test the step to confirm the data reaches Zoho CRM, or that a sample record comes back for a trigger.
7. Save and activate your workflow. Activating a workflow with a Zoho CRM trigger registers the notification with Zoho.
> **Note**
>
> Softr connects to Zoho CRM with OAuth, and your data center is detected automatically. Connect with a Zoho user whose profile can see the modules and fields you plan to use — records and fields that user cannot access do not appear in Softr. Triggers also need permission to receive notifications from Zoho; if you connected Zoho CRM before triggers were available and a trigger cannot be turned on, reconnect the account.
---
# Zoom integration
Source: https://docs.softr.io/workflows/integrations/zoom
Connect Zoom with your Softr applications to automate meeting scheduling, share join links instantly, and keep your team aligned. Build workflows that create Zoom meetings on demand and push the details to the people and tools that need them — all without code.
## Overview
The Softr Zoom integration allows you to connect your no-code apps with your Zoom account. Automatically schedule Zoom meetings whenever key events occur in your Softr app — such as form submissions, booking confirmations, or status changes — and use the returned meeting details (join URL, meeting ID, password) in any downstream step of your workflow.
With Softr, you can spin up scheduled Zoom meetings on the fly and feed the details into emails, database records, Slack messages, or any other workflow action.
## Available Actions
### Create meeting
Schedule a new Zoom meeting on the connected user's account. Configure the topic, start time, duration, timezone, password, agenda, and meeting options such as host video, participant video, mute upon entry, waiting room, join before host, and automatic recording. The action returns the meeting ID, join URL, start time, password, and topic so they can be used by subsequent workflow steps.
## Key Benefits
- **No-code simplicity:** Set up and manage your Zoom workflows visually in Softr, without any technical setup.
- **Instant scheduling:** Create Zoom meetings automatically the moment a trigger fires, with no manual setup.
- **Customizable meeting options:** Control video, audio, recording, and waiting room behavior on every meeting.
- **Seamless handoff:** Pass meeting details into any downstream action — email, database, Slack, and more.
## Example Use Cases
| Use Case | Description |
| :--------------------------------- | :------------------------------------------------------------------------------------------------ |
| **Booking confirmation** | Create a Zoom meeting when a customer books a session and email them the join link automatically. |
| **Sales call automation** | Schedule a Zoom call when a new lead reaches a qualified stage in your CRM. |
| **Interview scheduling** | Generate a Zoom meeting for each candidate and send the link to both interviewer and candidate. |
| **Office hours and consultations** | Spin up a Zoom meeting per submission and store the join URL in a Softr database. |
| **Internal team syncs** | Auto-create a Zoom meeting and post the join link to a Slack channel when a workflow runs. |
## Prerequisites
- An active Softr account with access to **Workflows**.
- A Zoom account with permission to create meetings (any paid or free Zoom plan that allows scheduling meetings via the Zoom Web Portal).
- Permission to authorize third-party apps on your Zoom account. If your Zoom account is managed by an admin, the admin may need to pre-approve the Softr app on the Zoom Marketplace.
## Adding the Softr Zoom integration
Follow these steps to install and authorize the Zoom integration inside Softr.
1. Sign in to your Softr workspace and open the application where you want to use the integration.
2. In the left sidebar, click **Workflows** and either open an existing workflow or click **New workflow**.
3. Choose a trigger for your workflow (for example, a one-time schedule, a form submission, or a record creation).
4. On the workflow canvas, click the **+** below the trigger and select **Add a new action**.
5. In the **Select an action** modal, search for `Zoom` and pick **Zoom → Create meeting**.
6. The action panel opens on the **Settings** tab. In the **Account** field, click the dropdown and choose **Add another account**.
7. A confirmation dialog appears. Click **Continue** to be redirected to Zoom's OAuth consent screen.
8. Sign in to your Zoom account if prompted, review the requested permissions, and click **Allow**.
9. You are redirected back to Softr. The connected Zoom account now appears in the **Account** field, formatted as `Zoom — () #N`.
10. Fill in the action inputs (topic, start time, duration, etc.), click **Continue**, and turn on the workflow.
If anything goes wrong during installation, see the [Troubleshooting](#troubleshooting) section below.
## Using the Softr Zoom integration
Once the integration is connected, you can use the **Create meeting** action in any Softr workflow.
### Create meeting
Schedules a new meeting on the connected Zoom account.
**Inputs**
- **Account** — the connected Zoom account that will own the meeting.
- **Topic** (required) — the meeting title shown in Zoom and in the join page.
- **Start time** — the date and time the meeting is scheduled to begin. Supports static values, dynamic values from previous workflow steps, and the **Current date & time** chip.
- **Duration** — meeting length in minutes.
- **Timezone** — the IANA timezone for the start time (for example, `Europe/Paris`).
- **Password** — optional 6+ character meeting password.
- **Agenda** — optional description shown in the meeting details and calendar invites.
- **Host video / Participant video** — whether host and participant cameras are on when joining.
- **Mute upon entry** — automatically mute participants as they join.
- **Waiting room** — require participants to be admitted from a waiting room.
- **Join before host** — allow participants to join before the host arrives.
- **Auto recording** — record the meeting automatically (`none`, `local`, or `cloud`).
**Outputs**
The action returns the meeting details so they can be used in any subsequent workflow step:
- `meetingId` — the Zoom meeting ID.
- `joinUrl` — the URL participants use to join the meeting.
- `startTime` — the scheduled start time returned by Zoom.
- `password` — the meeting password.
- `topic` — the meeting topic.
**Tips**
- Use the **Test** button on the action's **Testing** tab to create a real meeting on your Zoom account and inspect the response before turning the workflow on.
- Reference the action's outputs in later steps using `${actionId.field}` (for example, send `${createMeeting.joinUrl}` by email).
- Sensitive fields like the meeting password are obfuscated in workflow logs.
## Removing the Softr Zoom integration
To remove the Zoom integration, disconnect it from Softr. This fully deauthorizes the app and revokes the OAuth tokens.
1. Open your Softr workspace and navigate to the workflow that uses Zoom.
2. Open the Zoom action and click the **Account** dropdown.
3. Remove the connected Zoom account from the list (or disconnect it from your workspace's connected accounts under **Settings → Integrations**).
4. Softr automatically calls Zoom's token revocation endpoint to invalidate the OAuth tokens for that account.
After removal, Softr deletes the stored OAuth tokens and any cached account metadata associated with that Zoom user. The connected account no longer appears in the **Account** dropdown, and workflows that referenced it will fail with an authentication error on their next run until a new Zoom account is connected. No data from your Zoom account (other than the basic profile fields used to label the connected account) is stored by Softr, so no additional data deletion steps are required.
## Troubleshooting
**The OAuth popup closes without connecting my account.**
- Make sure third-party cookies and popups are enabled for `softr.io` in your browser.
- If your Zoom account is managed by an organization, an admin may need to pre-approve the Softr app on the Zoom Marketplace before users can install it.
**The Account dropdown is empty after authorization.**
- Refresh the workflow editor and reopen the action panel.
- If the connected account still doesn't appear, remove the integration (see above) and reconnect.
**The Create meeting action fails with an authentication error.**
- The connected Zoom account may have been removed from the Zoom Marketplace, or the OAuth tokens may have been revoked. Reconnect the account from the action's **Account** field.
**The meeting is created but the start time is wrong.**
- Check the **Timezone** input. The start time is interpreted in the timezone you select on the action.
**Scheduling meetings on behalf of another user fails.**
- Scheduling for another user requires that the other user has granted scheduling privileges on Zoom and that your Zoom plan supports scheduling privileges.
If your issue isn't covered here, please reach out using the [Contact support](#contact-support) section below.
## FAQ
**Which Zoom permissions does Softr request?**
Softr requests two scopes: `meeting:write:meeting` (to create scheduled meetings on your account) and `user:read:user` (to read your basic profile so the connected account can be labeled in Softr's UI). No other scopes are requested.
**Does Softr store my Zoom password or meeting recordings?**
No. Softr never sees your Zoom password — authorization happens through Zoom's OAuth flow. Softr does not access, download, or store Zoom recordings.
**Can multiple Zoom accounts be connected to the same Softr workspace?**
Yes. You can connect multiple Zoom accounts and pick which one each action uses via the **Account** dropdown.
**Will Softr send me email updates about the integration?**
Softr only sends transactional emails related to your workspace. You can manage email preferences from your Softr account settings.
**What happens to scheduled meetings if I disconnect the integration?**
Meetings that were already created on Zoom remain on the Zoom account — they are not deleted. Future workflow runs that reference the disconnected account will fail until a new Zoom account is connected.
---
# Softr Agents
Source: https://docs.softr.io/agents/overview
## Overview
Softr Agents let you build an AI assistant that holds a conversation, follows your instructions, and takes real actions across your apps, databases, and connected services.
You don't script every step. You describe what the agent is for and give it tools. The agent decides which tools to use, and in what order, to answer a question or finish a task. An agent can:
- **Chat** with your app users and respond in natural language.
- **Search a knowledge base** you upload (files or links) to give grounded answers.
- **Take actions:** read and write records in your data sources, send emails or Slack messages, search the web, and call external services.
- **Remember** relevant details about a user across the conversation.
- **Run on a schedule**, unattended, to handle recurring work.
> **Info**
>
> **Agents and Database AI Agents.** This page covers standalone **Agents**: assistants you connect to your apps or run on a schedule. They differ from [Database AI Agents](/softr-databases/ai-agents), which auto-fill and enrich individual fields in a Softr Database table. The two work well together.
## Agent types
When you create an agent, you first choose **how it runs**. This can be changed later.
- **App agent:** Users chat with this agent from selected apps. Use it for support assistants, in-app helpers, and anything a person talks to directly.
- **Scheduled agent:** Runs on a recurring schedule, with no live user. Use it for recurring reports, data cleanup, sync jobs, and other background tasks.

_The Choose an agent type dialog_
### The app as context for an App agent
When you connect an App agent to a Softr app, the app becomes a source of tools and data for the agent, the same way the [App MCP Server](/app-mcp-server) exposes an app to external AI assistants. The agent reads and acts on your app's data **as the signed-in user who chats with it**. It never acts as an admin or as the app itself.
So the agent can only do what that user can already do in the app:
- **The blocks you build decide what's possible.** A list, grid, or table lets the agent **read** records. A form lets it **create** records (only the fields the form shows). A profile or inline editing lets it **update**. A delete action lets it **delete**.
- **If no block shows a table, the agent can't touch that table**, even if the data source contains it.
- **User groups, page visibility, and data restrictions still apply.** Each user sees the same records and actions through the agent as they see in the app.
> **Tip**
>
> To widen or narrow what an App agent can do, change what the app shows. Add a form to allow record creation, add a list to allow reading, or restrict a block by user group to limit access. See [App MCP Server](/app-mcp-server) for the full model of how an app exposes its data.
## Step-by-step: Create your first agent
1. **Create an agent**
From your Softr dashboard, open **Agents** in the left sidebar. Click **Create**, or **Create your first agent** if you have none yet.

_The Agents page lists every agent in your workspace_
2. **Choose an agent type**
In the **Choose an agent type** dialog, pick **App agent** (users chat with it from your apps) or **Scheduled agent** (runs on a recurring schedule). Click **Next**. You can switch types later in the agent's configuration.
3. **Set up the agent profile**
In the editor, give your agent a title and set up its profile:
- **Model:** Choose the AI model that powers the agent. Models are grouped by cost, so you can balance capability and price (see [Choosing a model](#choosing-a-model)).
- **Reasoning effort:** For models that support it, choose how much the model thinks before it answers: **Off**, **Low**, **Medium**, or **High**. Higher effort gives better results on complex tasks, but it is slower and costs more.
- **Instructions:** Describe how the agent behaves and responds. State its goal, what it must always do, and what it must never do.

_The agent editor: connected apps, tools, knowledge, and instructions_
4. **Connect it to your apps or add a schedule**
Depending on the agent type:
- **App agent:** In the **Connected apps** card, click the **+** button to choose the Softr apps where the agent is available. You can **Test** the agent in each connected app.
- **Scheduled agent:** In the **Schedules** card, click the **+** button to create a recurring schedule. Set the frequency and a timezone. You can also add a message that starts each run.

_The Connect apps dialog_

_The Add schedule dialog_
5. **Add tools**
In the **Tools** card, click the **+** button to choose what the agent can do, such as read and write records in a data source, send an email, or post to Slack. Set each tool's authentication. You can also require confirmation before the tool runs. See [Tools & actions](#tools--actions).

_The tool picker: Softr and built-in tools, and integrations_
6. **Add knowledge (optional)**
In the **Knowledge** card, click the **+** button to upload files or insert links the agent can search when answering. See [Knowledge](#knowledge).

_The Add knowledge dialog_
7. **Test and turn it on**
Use the **Test agent** panel on the right to run the agent and watch its responses and tool calls. When you're happy, enable the **Agent enabled** toggle and click **Turn on** to publish it. If you edit a published agent, a banner tells you that your draft differs from the live version. Click **Update** to publish your changes.

_The Test agent panel shows the tool calls and the answer_
## Choosing a model
Softr offers models from several providers, grouped by cost tier. Pick based on the task:
| When you need | Consider |
| ---------------------------------------------------------- | ------------------------------------------------------------------------------- |
| The most demanding reasoning, coding, and agentic tool use | A top-tier model (for example a flagship GPT, Claude Opus, or Gemini Pro model) |
| A strong balance of capability, speed, and cost | A mid-tier model (for example Claude Sonnet or a Gemini Flash model) |
| Fast, cost-efficient handling of simple, high-volume tasks | A lightweight model (for example a mini, nano, or lite model, or Claude Haiku) |
> **Tip**
>
> Start with a balanced model. Move up to a flagship model only if the agent struggles with multi-step reasoning. A lightweight model keeps costs down for simple, repetitive tasks.
**Bring your own key (BYOK).** On higher plans, you can use your own LLM provider API key. Your provider account then bills the agent usage, and it doesn't use Softr AI credits.
## Tools & actions
Tools are the capabilities an agent can use when it responds. Actions are tools tied to a specific integration, such as "Slack: send channel message" or "Google Sheets: create row."
Native actions include:
- **Softr:** Read, create, update, and delete records.
- **Google Sheets:** Read, create, update, and delete rows.
- **HubSpot:** Read, create, update, and delete objects (for example contacts and deals).
- **Gmail:** Send emails and create drafts.
- **Slack:** Send channel messages, send direct messages, and find users.
- **Send email:** Send an email with Softr's built-in email service.
> **Note**
>
> **Airtable, Notion, and monday.com** connect through a [predefined MCP server](#predefined-mcp-servers), not through individual actions. Connecting one gives the agent all the tools of that service. Other data and productivity services (Attio, Apollo, Supabase, Linear, and more) are available the same way.
When you add a tool, you configure:
- **Authentication:** Choose **Per user authentication** (uses each user's own account or permissions) or **Shared authentication** (uses one shared account or connection).
- **Ask for confirmation:** When on, the agent shows a summary and waits for the user's approval before it runs the action. Scheduled agents don't have this option, because they run without a live user.
- **Configure input fields:** For each field, choose **Agent decides** (the agent fills it in at run time) or **Custom** (you set a fixed value the agent can't change).
## Connecting an MCP server
Agents can connect to external tool servers through the Model Context Protocol (MCP) to get more tools. Connect a **predefined MCP server** in a few clicks, or add a **Custom MCP** server with your own URL.
### Predefined MCP servers
Softr offers ready-made connections with the server URL already set. You only authenticate. They include:
- **Softr Databases:** Read and manage your database tables.
- **Airtable:** Read and manage bases, tables, and records.
- **Notion:** Search and edit pages and databases.
- **monday.com:** Manage boards, items, and updates.
- **Attio:** Manage CRM records, lists, and notes.
- **Apollo:** Search contacts and enrich leads.
- **Brevo:** Manage contacts and email campaigns.
- **Calendly** and **Cal.com:** Schedule and manage bookings.
- **Fathom** and **Granola:** Access meeting recordings, summaries, and notes.
- **Linear:** Manage issues, projects, and cycles.
- **Supabase:** Query and manage your database.
- **Clay:** Enrich and research data.
- **Apify:** Run scrapers and automation actors.
- **Replicate:** Run and manage AI models.
- **Atlassian:** Work with Jira issues and Confluence pages.
Pick a predefined server, authorize it, and choose which of its tools the agent can use.
> **Tip**
>
> A native **tool** (see [Tools & actions](#tools--actions)) gives the agent one narrow action with control per field. A predefined MCP server gives the agent all the tools of a service at once. Choose native actions to limit exactly what the agent can do. Choose MCP for broader access.
### Custom MCP server
To connect your own MCP server, provide:
- **Name:** A label for the server, such as "Internal knowledge base".
- **Server URL:** The MCP server endpoint.
- **Authentication:** **OAuth**, **Headers** (for example an `Authorization` header), or none.
For each tool the server exposes, set a permission:
- **Allow:** Always allow the call, with no prompt.
- **Ask:** Require user approval before the call runs. Scheduled runs approve the call automatically.
- **Deny:** Never allow the call. The agent doesn't get the tool.
> **Note**
>
> Write actions (those that change data) require approval by default. Read-only tools are safer to allow. Review the permissions before you turn the agent on.
## Knowledge
Add files or links the agent can search when answering. Softr indexes uploaded files (PDF, TXT, MD) and links, so the agent can find and cite relevant passages.
Each source has a status while Softr processes it:
- **Pending**, then **Indexing**, then **Ready:** the agent can search the source.
- **Failed:** indexing didn't finish. Remove the source and add it again.
Knowledge grounds an agent in your own content, such as product docs, policies, and FAQs. The agent answers from your material instead of guessing.
## Testing & runs
Use the **Test agent** panel to run the agent and watch it work: its streamed response, the tools it calls, and the tasks it plans.
Open the **Runs** panel to review every run. Each run records:
- **Model** and **Provider**
- **Duration** and **Tool calls**
- **Credits charged** and **Token usage** (input, cached, output, total)
- **Finish reason**, plus a **Run failed** badge and a **Show errors only** filter for troubleshooting

_A run with its details and transcript_
## Pricing and credits
Agent runs use **AI credits**. The credits a run uses depend on the model, the number and size of tool calls, knowledge search, and output length.
Every Softr plan, including Free, comes with a monthly amount of AI credits. If you use them all, AI features pause until your credits reset with your plan or you add more with a credit add-on. On higher plans, you can also [bring your own API key](#choosing-a-model), so your provider bills the usage. [Learn more about AI credits](/workspace-and-billing/jZP6yaeXMiJCuB6HhS4xKd/ai-credits/5VRMhf7Q6xvy7AJqyiQLx5)
## FAQ
**What's the difference between Agents and Database AI Agents?**
**Agents** (this page) are standalone AI assistants. They chat with your users or run on a schedule, and they take actions across your apps, data sources, and connected services.
**[Database AI Agents](/softr-databases/ai-agents)** work inside a Softr Database table. They auto-fill, tag, summarize, or enrich individual fields when records are created or updated.
Both use AI credits, and you can use them together. For example, a Database AI Agent classifies a record, and a standalone Agent follows up based on that value.
**Do I need to code to build an agent?**
No. You set up agents visually: pick a model, write plain-language instructions, add tools and knowledge, and turn the agent on. A custom MCP server is optional. You only need it to give the agent your own external tools.
**Can my app users chat with an agent?**
Yes. Create an **App agent** and connect it to one or more Softr apps. Your users then chat with it inside the app. You choose the apps where it appears.
**Can an agent run automatically without a user?**
Yes. Create a **Scheduled agent** and add a recurring schedule with a timezone. It runs unattended on that schedule. Use it for reports, cleanup, and sync jobs.
**Can I connect my own tools?**
Yes. Add a **Custom MCP** server, or pick a predefined one, to give the agent external tools through the Model Context Protocol. You set an Allow, Ask, or Deny permission for each tool.
**Which model should I pick?**
Start with a balanced mid-tier model. Move up to a flagship model for demanding multi-step reasoning. Move down to a lightweight model for simple, high-volume tasks. See [Choosing a model](#choosing-a-model).
**How are agents billed?**
Agent runs use AI credits, which every plan includes. Usage depends on the model, tool calls, knowledge search, and output length. On higher plans you can bring your own API key. [Learn more about AI credits](/workspace-and-billing/jZP6yaeXMiJCuB6HhS4xKd/ai-credits/5VRMhf7Q6xvy7AJqyiQLx5)
---
# Softr Forms
Source: https://docs.softr.io/softr-forms
Create and publish powerful, conditional forms—without limits, workarounds, or extra tools.
Use Softr Forms to create onboarding and request forms, surveys, event RSVPs, feedback forms, lead capture flows, and more, all in a visual, easy-to-use builder. Form responses are stored automatically in a built-in Softr Database, or send them to external tools, automations, email, or webhooks.
**Note: If you’re building a form inside a Softr app, use the \*\*Conditional Form Block**\*\***, which lets you build forms directly into app pages and connect them to app-specific workflows and permissions.**
## What you can do with standalone forms
- **Build flexible, conditional forms:** Create multi-step forms with conditional logic, validation rules, custom styling, and personalized endings using a visual builder.
- **Connect form data to your tools:** Store submissions in Softr Databases by default, or route data to external data sources (e.g. Airtable, Notion, Google Sheets, [monday.com](http://monday.com)), automation tools (Zapier, Make), email, or webhooks.
- **Control access and data quality:** Restrict who can submit forms using domain restrictions or email verification, and collect cleaner data with built-in validation and tooltips.
- **Share or embed forms anywhere:** Publish forms via a direct link, use a custom domain, or embed them on any website.
- **Build for free:** Create unlimited forms with unlimited submissions, including on the Free plan. **Note: The Conditional Form Block** (for Softr apps) is available on the Professional plan and higher.\_
## Video
---
## How to set it up
### 1. Create a new form
- Go to **Forms** in the left navigation
- Click **Create new form**
### 2. Choose where submission data is sent
- Under **Settings > Destination** on the right panel, select where form submissions should go:
- Softr Database (Built-in database) is the default setting
- To connect to an external data source (Airtable, Notion, Google Sheets, and more), automation tool (Zapier or Make), Email, or Webhook, click **Integrations** from the dropdown and follow the steps for configuration.
- You can also access connected data from the **Data** tab at the top of the builder.
- From **Settings > Options**, you can also set domain restrictions or enable reCaptcha.
### 3. Set domain restrictions (optional)
- From **Settings > Options**, you can enable domain restrictions, where users must verify their email with a one-time code.
- From here, you can also enable reCaptcha.
### 4. Build your form
- From the **Steps** tab on the right panel, add **steps, fields, and sections** to build your form.
- Field types include: Dropdown, Quick Select, Short text, Long text, Email, Date, Date time, File, Checkbox, URL, Number, Rating, Phone Number, Signature, and Address.
- Use the **Logic** tab to configure conditional logic between steps and fields.
- Customize appearance from the **Styles** tab (note: you can also apply global style settings from the **Theme** section in the left navigation).
- From **Settings > Side Section**, you can enable to add a split screen/background image to your form
- From **Steps > Ending**, set the form ending (confirmation message and next action).
### 5. Set field validation rules and tooltips (optional)
- For each field, open the input settings and scroll to **Validation** to define rules (including custom regex validation).
- For Email fields, you can use **Validation > Allow only specific email domains** to restrict submissions.
- From input settings, you can also set a **Tooltip** (under **Label**), along with a **Placeholder**, **Hint**, or **Default** value.
### 6. Publish and share or embed
- Click **Publish** and choose a subdomain or custom domain.
- Copy the link to share the form.
- Embed the form on any website by clicking the **Publish** button again (after the form has been published) and clicking Embed to copy the embed code.
## ✅ Things to keep in mind
- You can create and publish **unlimited Softr Forms with unlimited submissions,** even on the Free plan
- If you’re building a form inside your app, use the Conditional Forms block → see **Conditional Forms** (App Building Block) for details. This block is available on the Professional plan and higher.
---
# Airtable
Source: https://docs.softr.io/data-sources/airtable
Airtable is a powerful tool that combines the flexibility of spreadsheets with the power of a database. It allows you to store and organize different types of data, making it a great choice for managing data in your **Softr app.**
With Airtable, you can:
- Store text, images, checkboxes, and more
- Create custom views to **filter and sort** your data
- Control who can **view or edit** information
- Use **ready-made templates** to speed up setup
- Integrate with **third-party tools**
In this article, we’ll walk you through **connecting your Airtable account** to Softr and **displaying your Airtable data** in your app. For a quick overview, check out our video walkthrough. 👇
> **Info**
>
> Airtable is available on all plans, including Free.
## **1. Connect your Airtable account**
You connect an Airtable account once per workspace. Then you can use it in all your apps.
1. **Open Integrations**
1. In the [Softr Studio dashboard](https://studio.softr.io/dashboard/integrations), click **Integrations** in the left menu.
2. Click **Connect new**.

3. In the **Select an integration** window, click **Airtable**.

2. **Grant access to your Airtable bases**
Softr opens Airtable in a new window. Sign in to Airtable, select the bases you want to use in Softr, and click **Grant access**.
> **Warning**
>
> When granting access, we **strongly recommend** choosing **“All current and future bases in all current and future workspaces.”**
>
> If you don’t, you’ll need to manually reselect bases every time you reconnect, which could break your apps.

_Granting access to Airtable bases_
## **2. Connect your Airtable Base to the Softr app**
Once your Airtable account is connected, you can use the authorized bases across one or multiple Softr applications.
1. **Connect your data to a dynamic block**
To display your data in the app, connect a [dynamic block](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/visualize-data-with-building-blocks/41p6U2eZs7zgY8zWmFV4eH#1859a723d691803d9551ecd7b3b0c043) (e.g. [List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU), [Grid](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/grid-block/42JZoeYwMsogZcveqh74QH), [Table](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/table-block-/j7rGwu7J7zuU69h3bZ7HFe)) to your Airtable base:
1. Open the **Source** tab of the block settings.
2. In **Account**, select your Airtable account.
3. In **Base**, pick the base you want to use.
4. In **Table**, choose the table with the records you want to show.
5. Optional: in **View**, choose an Airtable view.
> **Warning**
>
> **Important:** Each Airtable table can only connect to one Softr block. For example, if you want to display **Projects** in a List block, you’ll need to map it to the **Projects table** in your base. If you also want to show **Tasks**, you’ll need to add a separate block and connect it to the **Tasks table**.

_The Source tab of a List block connected to Airtable_
> **Info**
>
> **Tip**: You can also select an Airtable **View** to display. If a view is selected, any filters and sorting applied in Airtable will be preserved for the records shown in the Softr block (e.g., showing only completed tasks).
2. **Map Airtable columns to item fields**
When you connect your table to a block, you can choose which Airtable **columns** to display. Open the **Content** tab, then click **Add** under **Item fields**. Each column maps to a field of the block. This lets you control how your Airtable data appears in Softr.
**Example:** If your Airtable base has a **Profile Picture (Attachment field)**, map it to an **Image field** in Softr so it displays correctly.

_Airtable fields_

_Mapping an image field_
> **Info**
>
> Airtable fields work like **spreadsheet columns**, but each has a specific type (e.g., text, image, checkbox). To keep everything working smoothly, make sure to **match field types correctly** when setting up the connection.
## **3. Supported field types**
Softr handles Airtable field types in three ways:
1. **Fully supported** – You can read and update these fields.
2. **Read-only** – You can see the data, but you can’t edit it.
3. **Not supported** – These fields won’t sync with Softr.
### **Fully supported Airtable field types**
- **Text** – Single line, long text, and rich text
- **Number** – Standard numbers, currency, and percentages
- **Date & Time** – Date, date-time, and duration fields
- **Attachments** – Images, multiple attachments, and files
- **Checkbox** – Yes/No options
- **Linked Records** – Connects one table to another
- **Single & Multi-Select** – Dropdown lists
- **Email & Phone** – Email addresses and phone numbers
- **Rating** – Star or point-based ratings
- **URL** – Website links
- **User Fields** – Created by, last modified by, and collaborator fields
### **Fields that can be shown but not edited**
Some fields are **read-only** in Softr because Airtable automatically generates them:
- **Formula Fields** – Calculated values
- **Rollup, Count, and Lookup Fields** – Pull data from other tables
- **Created By & Created Date** – Who and when a record was created
- **Last Modified By & Last Modified Date** – Who and when a record was updated
- **Autonumber Fields** – Automatically assigned numbers
### **Not supported fields**
These fields are not supported due to Airtable API limitations:
- **Button Fields** – Trigger actions but don’t store data
- **Barcode Fields** – Store scanned barcode data
- **Sync Source** – Data synced from external sources
## **FAQs**
**What if I can’t see my Airtable bases in Softr?**
Check that you’ve granted **Softr access to all current and future bases** in Airtable. If not, go back to [**Integrations**](https://studio.softr.io/dashboard/integrations) and re-authenticate.
**Why aren’t my mapped fields showing?**
If some fields aren’t displaying data even though they are mapped correctly, check if their titles in Airtable contain any [special characters](https://www.computerhope.com/jargon/s/specchar.htm). Removing special characters can help resolve the issue.
**Why is my data not updating in Softr?**
Try refreshing Softr or reloading your data source. If the issue persists, check if your **Airtable permissions** are correctly set.
**Can I use multiple Airtable bases in one Softr app?**
Yes! You can connect multiple Airtable bases to the same app, but you have to use a separate [Dynamic Block](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/visualize-data-with-building-blocks/41p6U2eZs7zgY8zWmFV4eH) for each table.
**How can I improve my app's performance?**
### OAuth vs. personal access token rate limits
Airtable limits each base to 5 requests per second, whatever the authentication method. A personal access token gives Softr more room across several bases. Requests to one base stay capped at 5 per second.
### Free plan rate limits
Airtable Free plan users are limited to 1,000 API calls per month. When you reach this limit, Airtable blocks all API requests until the monthly reset.
### Using a personal access token
A personal access token lets you control which bases and scopes Softr can reach in your Airtable account.
To switch an existing connection, click **Switch to personal access token** below the integration name in **Integrations**. Then paste your token in **Personal access token** and click **Connect**.

Give the token the **Record data**, **Base schema**, **Webhook**, and **User email** scopes, with access to **all current and future bases**. Create it in the [Airtable developer hub](https://airtable.com/create/tokens).

Follow [this Airtable guide](https://airtable.com/developers/web/guides/personal-access-tokens) to generate a token.
## **Need more help?**
- ▶️ Watch a tutorial on [how to structure your Airtable database for Client Portal](https://youtu.be/sqLdl3HJwd4?si=CcMV-kW2e425obRA)
- 📖 Learn more in our [Airtable Learning Hub](https://www.softr.io/airtable)
- 🛠️ Troubleshooting? Check out [Troubleshooting Airtable errors](https://softrdocs.helpkit.so/troubleshooting/c7mbQk6nyqGUTGoVjojr9E/troubleshooting-airtable-errors/9ZYLgZxAhfSCth2F4HRXtw)
---
# HubSpot
Source: https://docs.softr.io/data-sources/hubspot
HubSpot is an integrated marketing, sales, and customer service platform that provides businesses with tools to attract, engage, and delight customers throughout their lifecycle.
It can also act as a relational database. To learn more about HubSpot and its features, visit the [official HubSpot website](https://www.hubspot.com/).
In this article, we will cover how to connect HubSpot and then take a closer look at some of the features that are important to consider in that context.
> **Info**
>
> **HubSpot** integration is available on **Business** and **Enterprise** plans.
## 1. Connect your HubSpot account
To use HubSpot in Softr, you must first **connect your HubSpot account**. Any HubSpot data source you connect in Softr can be used by all of the workspace's collaborators in all of the workspace’s apps.
> **Warning**
>
> To connect HubSpot, you must have HubSpot Super Admin access.
1. **Add HubSpot data source to your workspace**
1. In Softr Studio, click **Integrations** in the left menu.
2. Click **Connect new.**

_The Integrations page, with the Connect new button._
3. In the **Select an integration** window, click **HubSpot.**

_The Select an integration window\._
4. Proceed to authenticate your account.
2. **Grant access to HubSpot**
1. Sign in to your HubSpot account.
2. Select which account you want to connect to Softr.

## 2. Connect your HubSpot data to a Softr app
Once your HubSpot account is connected, you can use the authorized account across one or multiple Softr applications.
1. **Connect the HubSpot objects to a Dynamic Block**
To display your data in the app, connect a [dynamic block](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/visualize-data-with-building-blocks/41p6U2eZs7zgY8zWmFV4eH#1859a723d691803d9551ecd7b3b0c043) (e.g. [List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU), [Grid](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/grid-block/42JZoeYwMsogZcveqh74QH), [Table](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/table-block-/j7rGwu7J7zuU69h3bZ7HFe)) to your HubSpot objects:
1. In the Block **source tab**, select the authenticated HubSpot integration.
2. Choose the **Object** you want to use.
> **Warning**
>
> **Important:** You can connect only one object type to one block. For example, if you want to show a list of clients, you can select the **Companies** object. If you would like to show **Tickets**, you will need to add another **dynamic block**.

_Selecting HubSpot objects._
### Supported HubSpot Objects
Softr supports the following **HubSpot objects**:
- **Contacts**
- **Companies**
- **Deals**
- **Tickets**
- **Notes**
- **Tasks**
- **Leads**
- **Projects**
- **Products**
- **Line Items**
- **Invoices**
- **Subscriptions**
- **Listings**
- **Appointments**
- **Custom Objects**
> **Note**
>
> Some objects appear only when your HubSpot account can share them. Softr hides an object
> when HubSpot does not grant access to it, so the list you see can be shorter than the list
> above. Invoices and Subscriptions, for example, need extra HubSpot permissions.
>
> If you expect an object and it is missing, reconnect the HubSpot data source and approve
> the access HubSpot asks for. The object appears right after that.
2. **Mapping HubSpot object fields**
When you select the object type you want to show, you can customize which object properties you want to visualize alongside. Each HubSpot object has **predefined field types** like text, dropdowns, and date pickers. Since Softr also has its field types, it's important to **map fields correctly** to ensure your data appears as expected.
For example, if a HubSpot **deal property** contains an image stored as a **File type**, you should map it to a **Softr Image field** in a **List block** so it displays correctly.

_Mapping HubSpot object properties._
### Supported Properties
Softr supports:
- All default HubSpot object properties
- All custom properties you’ve created in HubSpot
However, some **read-only fields** cannot be edited in Softr, including:
- Computed fields like **Calculation** fields, **Rollup**, **Count**, and **Formula** fields.
### HubSpot object associations
HubSpot works as a **relational database**, meaning objects can be linked together through **associations**. This allows you to display related data, such as:
- A **Deal** with multiple **Tasks** linked to it
- A **Company** associated with multiple **Contacts**
In Softr, you can show associated objects using:
1. [Linked List Block](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/linked-list/bWjTdKhbftofSEKRSxMFz9)
2. Associated Object IDs property
You can also use associated objects in [Visibility Conditional Filters](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/block-visibility/3spA2dfQNrcGcPNmnDXHB3), the same as with other data sources.
## FAQs
**Why can't I see certain HubSpot fields in Softr?**
Some HubSpot fields and objects require **Sensitive Data scopes** for API access. You may need to enable these permissions in HubSpot if certain data is missing or restricted. [Learn how to enable Sensitive Data Scopes in HubSpot](https://knowledge.hubspot.com/properties/store-sensitive-data).
**Can I use multiple HubSpot accounts in one Softr app?**
Yes! You can connect multiple HubSpot accounts but need to use **separate Softr blocks** for each object.
## Need More Help?
- 🛠️ Troubleshooting? Check our [Troubleshooting HubSpot errors](https://softrdocs.helpkit.so/troubleshooting/c7mbQk6nyqGUTGoVjojr9E/troubleshooting-hubspot-errors/3hLzPdvf8frTjFowAHKEMt).
- ▶️ Watch a tutorial on[how to create a Client Portal with HubSpot + Softr](https://youtu.be/uNss7EangWI?si=zunQ_lZC8ciAB4zF).
- 📖 Learn more about [HubSpot Chat](/integrations/etS18kJqm1fuD58KCsjC3z/hubspot-chat/4UocQQqLC2q288N74eoLfL).
---
# Salesforce
Source: https://docs.softr.io/data-sources/salesforce
Salesforce is the world's leading customer relationship management (CRM) platform, giving sales, service, and marketing teams a single source of truth for customer data.
Because Salesforce is a relational CRM organized around standard and custom objects, it makes an excellent data source for internal tools, client portals, and dashboards built on Softr. To learn more about Salesforce, visit the [official Salesforce website](https://www.salesforce.com/).
In this article, we'll cover how to connect Salesforce to Softr and take a closer look at the features that matter in that context.
> **Info**
>
> **Salesforce** as a data source is available on the **Enterprise** plan.
## 1. Connect your Salesforce account
To use Salesforce in Softr, you must first **connect your Salesforce account**. Any Salesforce data source you connect in Softr can be used by all of the workspace's collaborators in all of the workspace's apps.
> **Warning**
>
> To connect Salesforce, you must have permissions to authorize third-party OAuth applications in your Salesforce org. If your org restricts connected apps, ask your Salesforce administrator to approve Softr.
1. **Add Salesforce data source to your workspace**
1. Install the Softr app in your Salesforce org.
2. In the Softr Studio dashboard, click **Integrations** in the left menu.
3. Click **Connect new**.

4. Select **Salesforce** in the Select an integration window.

2. **Grant access to Salesforce**
1. In the Connect to Salesforce window, click **Connect**.

2. Sign in to your Salesforce account when redirected.
3. Choose whether to connect a **production** org or a **sandbox** org, then approve the requested permissions to complete the connection.
## 2. Connect your Salesforce data to a Softr app
Once your Salesforce account is connected, you can use the authorized account across one or multiple Softr applications.
1. **Connect Salesforce objects to a Dynamic Block**
To display your data in the app, connect a [dynamic block](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/visualize-data-with-building-blocks/41p6U2eZs7zgY8zWmFV4eH#1859a723d691803d9551ecd7b3b0c043) (e.g. [List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU), [Grid](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/grid-block/42JZoeYwMsogZcveqh74QH), [Table](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/table-block-/j7rGwu7J7zuU69h3bZ7HFe)) to your Salesforce objects:
1. In the block **source tab**, select the authenticated Salesforce integration.
2. Choose the **Object** you want to use.

> **Warning**
>
> **Important:** You can connect only one object type to one block. For example, if you want to show a list of accounts, select the **Accounts** object. To display **Opportunities** as well, add another **dynamic block**.
### Supported Salesforce Objects
Softr supports the following **Salesforce objects**:
- **Contacts**
- **Leads**
- **Opportunities**
- **Accounts**
- **Cases**
- **Custom Objects**
2. **Mapping Salesforce object fields**
When you select the object type you want to show, you can customize which object fields to visualize. Each Salesforce object has **predefined field types** like text, picklists, dates, and lookups. Since Softr also has its own field types, it's important to **map fields correctly** to ensure your data appears as expected.
For example, if a Salesforce **Opportunity** stores an attached image URL in a **URL field**, map it to a **Softr Image field** in a **List block** so it displays correctly.
### Supported Fields
Softr supports:
- All standard Salesforce object fields
- All custom fields you've created in Salesforce
However, some **read-only fields** cannot be edited in Softr, including:
- **Formula** fields, **Rollup Summary** fields, and system audit fields such as **Created By**, **Last Modified By**, and **System Modstamp**.
### Salesforce object relationships
Salesforce works as a **relational database**, meaning objects can be linked together through **lookup** and **master-detail** relationships. This allows you to display related data, such as:
- An **Account** with multiple **Contacts** linked to it
- An **Account** with multiple **Opportunities** linked to it
In Softr, you can show related objects using:
1. [Linked List Block](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/linked-list/bWjTdKhbftofSEKRSxMFz9)
2. Related record ID fields
**Limitations**
> **Warning**
>
> Related objects cannot currently be used in [Visibility Conditional Filters](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/block-visibility/3spA2dfQNrcGcPNmnDXHB3).
## FAQs
**Why can't I see certain Salesforce fields in Softr?**
Salesforce enforces **field-level security** and **profile permissions** on the API user account that authorized the connection. If a field or object is missing in Softr, verify that the authorizing user's profile and permission sets grant read (and, where needed, edit) access to those fields.
**Can I connect a Salesforce sandbox?**
Yes. When connecting Salesforce, choose the **sandbox** option to authenticate against `test.salesforce.com` instead of your production org. This is useful for testing your Softr app against non-production data before going live.
**Can I use multiple Salesforce orgs in one Softr app?**
Yes. You can connect multiple Salesforce accounts, but you'll need to use **separate Softr blocks** for each object from each org.
## Need More Help?
- 📖 Automate Salesforce records from your app with the [Salesforce workflow integration](/workflows/integrations/salesforce).
---
# Notion
Source: https://docs.softr.io/data-sources/notion
**Notion** is more than just a note-taking tool. It combines project management and databases, making it a stronger alternative to spreadsheets for organizing and collaborating on data in one place.
By using [Notion databases](https://www.notion.so/help/what-is-a-database) with Softr, you can easily create Client Portals, Internal Tools, and other business apps to:
- Offer a simple, user-friendly experience
- Control access to specific data
- Secure logins without Notion invites
- Let users submit, edit, and sync data seamlessly
- Collect forms, feedback, and inputs effortlessly
> **Info**
>
> Notion is available on all plans, including Free.
## **1. Connect your Notion account**
To use Notion in Softr, you must first **link your Notion account**. Here’s how:
You connect Notion once per workspace. Then you can use it in all your apps.
1. **Open Integrations**
1. In the Softr Studio dashboard, click **Integrations** in the left menu.
2. Click **Connect new**.

3. In the **Select an integration** window, click **Notion**.

You can also connect Notion from the **Account** list in the **Source** tab of a block.
2. **Start the connection**
In the **Connect to Notion** window, click **Connect**. Softr opens the Notion authorization page.

3. **Grant access to the Notion databases you want to use**
On the Notion authorization page, select the workspace. Then click **Select pages** to choose the top-level pages that contain the databases you want to connect to Softr.

> **Info**
>
> You can authorize the integration only for Notion workspaces where you are **a member.**

> **Info**
>
> Once connected, **only Notion database pages** can be used with Softr dynamic blocks, such as List and Detail blocks.
To finalize the connection, click the **Allow access** button to grant Softr permission to access your Notion account.
## **2. Connect your Notion database to your Softr app**
1. **Connect your data to a dynamic block**
To display your data in the app, connect a [dynamic block](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/visualize-data-with-building-blocks/41p6U2eZs7zgY8zWmFV4eH#1859a723d691803d9551ecd7b3b0c043) (e.g. [List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU), [Grid](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/grid-block/42JZoeYwMsogZcveqh74QH), [Table](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/table-block-/j7rGwu7J7zuU69h3bZ7HFe)) to your Notion database:
1. Open the **Source** tab of the block.
2. In **Account**, select your Notion account.
3. In **Database**, pick the database you want to use.
Each page of that database is a record in your app.

2. **Map Notion columns to item fields**
Once the block is connected to your database, open the **Content** tab. In **Item fields**, click **Add** to show a Notion property in each item.

In Notion, properties are essentially the columns in the database, with each property having a predefined type, such as **Files**, **Status**, **Date**, and more. Similarly, Softr offers a variety of field types to choose from when displaying your data. It's important to select the appropriate field type when mapping fields from Notion to Softr.
For example, in the image below, we’ve mapped a **File** property from Notion to an **Image** field type on Softr’s List block to display photos.

### **Supported fields**
Most fields that can be edited in Notion are also editable in Softr. However, there are exceptions. Fields that Notion generates, such as **Rollup, Formula, People, Created time, Created by, Last edited time, Last edited by** and **ID**, can be displayed but not edited within Softr.
> **Info**
>
> Softr does not support these Notion properties: **Button, Verification, Place.**
Why Dates Look Different in Notion and Softr
If dates from Notion show differently in Softr (e.g., "14-05-2025" instead of "15-05-2025"), it’s due to time zone handling in Notion formulas. Here’s why and how to fix it.
What’s Happening?
A Notion formula like format calmaDate(Data, "DD-MM-YYYY") pulls from a date field, e.g., "2025-05-14T22:00:00.000+00:00" (May 14, 2025, 10:00 PM UTC).
- Notion: Shows the date in your local time zone (e.g., Italian, UTC+2), where 10:00 PM UTC is midnight May 15, so it displays "15-05-2025".
- Softr: Uses UTC from Notion’s data, showing "14-05-2025" for May 14.
This mismatch occurs because the date includes a time (10:00 PM UTC), which shifts the day depending on the time zone.
Why Now?
Your Notion date field may have recently changed to use 10:00 PM UTC instead of midnight UTC, causing the day to shift in different time zones.
How to Fix It
1. Use Midnight UTCSet Notion dates to midnight UTC (e.g., "2025-05-14T00:00:00.000+00:00").How: In Notion, set dates to 12:00 AM UTC or exclude time.
2. Skip Time AltogetherUse only dates (no times) in Notion for consistent display.How: Set the date field to “Date Only” in Notion.
Best Option?
If times aren’t needed, choose Skip Time Altogether for simplicity. Otherwise, use Midnight UTC.
### Database relations
The [Relation](https://www.notion.so/help/relations-and-rollups) property in Notion is essential for creating a **relational database**. It allows you to link records from one database to another, enabling the seamless display of related information across your boards.
For example, if you have two Notion databases (**Clients** and **Projects**), you can add a Relation property to **Clients** to link it with **Projects**. This lets you easily display all projects associated with a specific client.

> **Info**
>
> Due to limitations in the Notion API, Relation fields cannot be displayed in List-type dynamic blocks (List, Table, Inbox, etc). As an alternative, we recommend creating a **Rollup field** based on the Relation field and using that for display.
### Conditional filters based on relation
[Conditional filters](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/conditional-filters/mDnn7jnpPiYmJcT99jpt7m) allow you to display specific records based on set conditions. This feature is handy when showing related records between databases. For example, if you have a "Client Detail" page, you can display a list of projects related to a specific client.

_Conditional filters with related record set up_

_Published application with conditional filter set up_
### How to show sub-items
If your database includes sub-items, here’s how you can choose what shows up in your Softr blocks.
**Show both items and sub-items**
When you connect your database to a dynamic block, you’ll automatically see both items and sub-items.

> **Info**
>
> Note: The block will display them as one flat list. It won't keep the parent-child hierarchy.
**Show only top-level items**
To hide sub-items and show only top-level items, in the **Source** tab, add this condition under **Record filters**: `Parent item - is empty`.

**Show only sub-items**
To show just sub-items (and hide the top-level items), in the **Source** tab, add this condition under **Record filters**: `Parent item - is not empty`.

**Show items with sub-items in a detail page**
Want users to click an item and see its sub-items on a new page? Here's how:
1. Filter the list to show only top-level items (`Parent item - is empty`).
2. In **Actions**, set **Action on click** → **Open detail page** (or create a one).
3. In the detail page, add a list block.
4. Set that block to show sub-items related to the current item:\
`Parent item - Includes any of → Current record {Primary column name}`

---
## FAQ
**My Notion is connected to Softr, but I don’t see the page or database I’m trying to access.**
This can happen when you add a page or database to Notion after you have already created the connection to Softr. To fix this, navigate to the page you want to give Softr access to and click on the ellipses icon in the upper right corner. Hover over the Connections, search for Softr and select it.

Notion will ask you to confirm letting Softr access this page. Note that you will need to refresh Softr editor to see the newly connected page or database.

**Can I use multiple Notion workspaces in one Softr app?**
Yes! You can connect multiple Notion workspaces but need to use **separate Softr blocks** for each database.
**Why do dates look different in Notion and Softr?**
If dates from Notion show differently in Softr (e.g., "14-05-2025" instead of "15-05-2025"), it’s due to time zone handling in Notion formulas. Here’s why and how to fix it.
### What’s Happening?
A Notion formula like format calmaDate(Data, "DD-MM-YYYY") pulls from a date field, e.g., "2025-05-14T22:00:00.000+00:00" (May 14, 2025, 10:00 PM UTC).
- Notion: Shows the date in your local time zone (e.g., Italian, UTC+2), where 10:00 PM UTC is midnight May 15, so it displays "15-05-2025".
- Softr: Uses UTC from Notion’s data, showing "14-05-2025" for May 14.
This mismatch occurs because the date includes a time (10:00 PM UTC), which shifts the day depending on the time zone.
**Why Now?**
Your Notion date field may have recently changed to use 10:00 PM UTC instead of midnight UTC, causing the day to shift in different time zones.
**How to Fix It**
1. Use Midnight UTCSet Notion dates to midnight UTC (e.g., "2025-05-14T00:00:00.000+00:00").How: In Notion, set dates to 12:00 AM UTC or exclude time.
2. Skip Time AltogetherUse only dates (no times) in Notion for consistent display.How: Set the date field to “Date Only” in Notion.
**Best Option?**
If times aren’t needed, choose Skip Time Altogether for simplicity. Otherwise, use Midnight UTC.
---
# Coda
Source: https://docs.softr.io/data-sources/coda
Coda is a powerful all-in-one document platform that combines tables, documents, and automations to create flexible, collaborative workspaces. By connecting Coda as a data source for your Softr app, you can transform your Coda tables into dynamic client portals, internal tools, or dashboards without coding. This guide will walk you through the steps to connect Coda to your Softr app, configure data syncing, and leverage Coda’s data to build customized, branded experiences.
> **Tip**
>
> Coda is available as a data source on the Professional, Business, and Enterprise plans.
## **Why Use Coda with Softr?**
Integrating Coda with Softr allows you to:
- **Centralize Data**: Bring Coda tables together with other data sources (like Airtable, Google Sheets, or REST APIs) in a single Softr app with real-time data read/write capability.
- **Create Custom Portals**: Build client or team portals with tailored views, pulling data from Coda tables, pages, or sections.
- **Customize Access**: Set granular permissions to control what users see or edit, based on roles or conditions.
- **Enhance Workflows**: Use Coda’s structured tables to power forms, dashboards, or internal tools with Softr’s powerful no-code interface.
- **Brand Your Experience**: Style your Softr app to match your brand, creating polished, professional interfaces for Coda data.
Softr is ideal for teams managing projects, documentation, or collaborative workflows in Coda who want to create user-friendly, secure, and visually appealing apps.
## Before You Start
Before connecting Coda to Softr, ensure you have:
- A **Softr account** with access to Coda as data source (available on Softr’s Professional plan and up).
- A **Coda account** with access to the doc(s) or table(s) you want to connect.
- Admin or editor permissions in Coda to generate an API token.
- A Softr app project set up in your Softr Studio dashboard.
## Setup
1. **Connect Coda to Softr**
1. **Log in to Softr Studio**:\
- Navigate to your Softr Studio dashboard at [studio.softr.io](https://studio.softr.io/).
2. **Open Integrations**:\
- In the left-hand menu, click **Integrations**.
- Click **Connect new**.

- In the **Select an integration** window, click **Coda**.

3. **Authenticate with Coda**:\
- The **Connect to Coda** window asks for your Personal API Token.

- To generate a Coda API token:
- In Coda, open **Account settings**.
- Go to the **API Settings** section and click **Generate API token**.
- Copy the token. Paste it into **Personal API Token**, then click **Connect**.
4. **Manage the Coda Connection**\
- Click the three dots next to the connection. Choose **Rename**, **Re-authenticate**, or **Remove**.
- Click **See active apps** to see a list of all the Softr apps that use the connection.

2. **Configure Data Mapping**
With Coda connected, you can now use its data to power your Softr app:
1. **Add Blocks**:\
- In your Softr app, go to the **Pages** menu and select or create a page.
- Add any dynamic blocks like **List**, **Table**, **Kanban**, or **Form** to display or interact with Coda data.
2. **Choose Document and Table**:\
- Select the block and open the **Source** tab.
- In **Account**, select your Coda connection.
- In **Document**, choose the Coda doc. In **Table**, choose the table to map to the block.

_The Source tab of a List block connected to a Coda table_
3. **Apply Filters and Conditions** (Optional):\
- In the **Source** tab, add conditions under **Record filters** to show only some rows. For example, show only tasks assigned to a specific user.

- Set visibility rules for different user roles. Open the **Visibility** tab to choose who can see the entire block. You can also set this for buttons in the **Actions** tab.

4. **Map Columns to Fields in Softr:**\
- Open the **Content** tab in the block settings.
- Under **Item fields**, click **Add** to choose the Coda columns you want to show. For example, names, statuses, dates, or attachments.
- Click a field to change its display type and styling. For a file column, choose **Image**.
- Softr supports Coda’s table columns, including text, numbers, dates, select lists, and attachments.

_Item fields of a List block_

_Mapping an image field_
3. **Build Your Softr App with Coda Data**
With Coda connected, you can now use its data to power your Softr app:
1. **Customize Layout and Styling**:\
- Use Softr’s dynamic, static, and container blocks to display Coda data and customize layouts.
- [Apply branding options](/styling/7qXYEkNvWQamR6vcLXzZnF/application-theme/91YGSL2aDJajXdbPBhitbc) (colors, fonts, logos) to match your organization’s style.
2. **Set Permissions**:\
- Go to the **Users** section in Softr Studio to configure user roles using [User Groups](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/user-groups/6XQfKMeKHUvBcAjKvLs3g3) (e.g., admin, client, team member).
- Use [page](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/page-visibility/nWJaN689VKA1TUeaEfzK9u), [block](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/block-visibility/3spA2dfQNrcGcPNmnDXHB3), or [button-level visibility](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/action-button-visibility/tqpb8TkUD4U4DCAUA2hjKo) to restrict access to sensitive Coda data.
3. **Add Interactive Features**:\
- Use [**Forms**](https://docs.softr.io/building-blocks/vikC2AWEpQGkZd4jGyoVxo/conditional-forms/afyKqnGDXd54U8d4xLNcsR) to collect data from users, which can sync back to your Coda table.
- Enable [**Comments**](https://docs.softr.io/building-blocks/vikC2AWEpQGkZd4jGyoVxo/comments/e2uAn1UjcxwdpcrDvE4ocN) blocks to allow user-specific discussions, with visibility controlled by conditions.
- Create **Dashboards** to visualize Coda data using charts or summary views.
4. **Test and Publish**
1. **Preview Your App**:\
- Use Softr’s preview mode to test how your app displays and interacts with Coda data.
- Verify that filters, permissions, and sync settings work as expected.

2. **Publish Your App**:\
- Click [**Publish**](https://docs.softr.io/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/publish-your-application/41p6U2eZs7mF8o4UyKai2g) in Softr Studio to make your app live.
- Share the app with users via a [custom domain](/publishing/9qTmU2Lj8Gnpr1Ue6dEAkX/add-a-custom-domain-to-your-app/93K5bLJN3n91MRo9uRGdAf), public link, or restricted access for logged-in users.

## **Best Practices**
- **Organize Your Coda Tables**: Structure your Coda tables with clear column names and consistent data types to simplify mapping in Softr.
- **Use Filters for Personalization**: Leverage Coda’s table structure to create filtered views in Softr (e.g., show only tasks due this week).
- **Secure Your Data**: Restrict API token access in Coda and use Softr’s [User Groups](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/user-groups/6XQfKMeKHUvBcAjKvLs3g3) and/or [Data Restrictions](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/global-data-restrictions/3kH6DuUvRNVztnGzAJoiL8) to create role-based permissions to protect sensitive information.
- **Combine Data Sources**: Integrate Coda with other sources (e.g., Google Sheets or HubSpot) in Softr to create a unified app experience.
## Keep in Mind
- **API Rate Limits**: Coda limits the number of API requests. Check [Coda’s documentation](https://help.coda.io/en/articles/9524803-overview-doc-limits) for details.
- **Complex Data Types**: Some Coda features (e.g., embedded docs or advanced automations) may not work or integrate directly with Softr, though you can do a lot with embedding with [custom code](/custom-code/3idxDhKqz1qPdqBuWbs61G/custom-code-block-overview/6XNrxFopUEiwbWipq81Eq1)!
- **Plan Requirements**: Data availability and advanced permissions may require specific Softr and Coda plans.
- **Attachment Handling**: Large files or attachments in Coda tables may take longer to load. Be sure to compress or convert files before uploading to Coda tables.
## **Troubleshooting**
- **Connection Issues**:
- Ensure your Coda API token is valid and has the correct permissions.
- Verify that the selected Coda doc and table are accessible to the account used for authentication.
- **Data Not Syncing**:
- Check sync settings in Softr and confirm two-way user sync is enabled if needed.
- Review Coda table permissions to ensure Softr can read/write data.
- **Display Errors**:
- Confirm that Softr field mappings match the data types in your Coda table.
- Test dynamic block filters and conditions to ensure they’re correctly applied.
For further assistance, contact Softr support via .
## **Example Use Cases**
1. **Client Portal**:\
- Use Coda to manage client projects and connect to Softr to create a branded portal where clients can view their project status, submit feedback via forms, or download files.
2. **Team Dashboard**:\
- Pull Coda data into a Softr dashboard to display team tasks, deadlines, or KPIs in a Kanban or chart view.
3. **Internal Knowledge Base**:\
- Sync Coda’s documentation tables to create a searchable, user-friendly knowledge base for your team or customers.
4. **Event Management**:\
- Use Coda to track event details and Softr to build a public-facing app for attendees to view schedules or register.
---
# Google Sheets
Source: https://docs.softr.io/data-sources/google-sheets
Google Sheets is a cloud-based spreadsheet solution used by millions worldwide. While it may not be as powerful as Airtable in terms of data management, it is a popular and free tool that many users already rely on. In this guide, we'll walk you through **connecting Google Sheets as a data source** for your Softr app and discuss some of its **advantages and limitations**. Google Sheets is available on all plans, including Free.
## **1. Connecting your Google Sheets account**
To start using Google Sheets in Softr, you must first connect your account.
- Open the **Integrations** page in the Studio sidebar.
- Click **Connect new**.

- Select **Google Sheets**. The **Connect to Google Sheets** window opens.
- Click **Connect**, then log in to your Google account.
- Check all required permission boxes.

## **2. Connect your Google Sheet data to your Softr app**
Once your Google Sheets account is connected, you can use it in any Softr application.
1. **Connect your data to a dynamic block**
To display your data in the app, connect a **dynamic block** to your Google Sheet.
1. Go to the block **Source** tab and select your Google Sheets account.
2. Select the **Document** you want to connect.
3. Select the **Sheet** you want to use.\

2. **Step 2. Mapping Google Sheets columns to Softr field**
> **Tip**
>
> When mapping Sheets data to Softr, it’s best to have at least 1 row of sample data in each table/sheet so that Softr can properly determine the field types.
Google Sheets stores data in a table format, where each **column represents a field**, and each **row is a record**. To ensure smooth integration, structure your sheet with:
- **The first row as field names** (e.g., "Assignee," "Status," "Description").
- **Data stored in rows** under the appropriate column headers.

_Field names and values on Google Sheets_
When you connect a block to a sheet, you can choose which sheet **columns** to display and map each one to a Softr field. In the block's **Content** tab, click an item field, such as **Photo**, to change how it displays. An image field needs a column that holds image URLs.

_Mapping an image column to an Image field_
### **Record ID Column**
Once you connect a sheet to Softr, a **Softr Record ID** column is automatically added. This unique ID helps Softr reference records (e.g., linking a List block to a List Details block).
> **Warning**
>
> **Ensure you have edit permissions** for your Google Sheet so Softr can add and update this column. Do not delete it.

_The Record ID column created inside the sheet_
> **Tip**
>
> **Tip**: Use **Softr Record IDs** to link related records across sheets (e.g., setting a "Manager ID" as another user's Softr ID).
### **Supported Field Types in Softr**
Google Sheets doesn’t have built-in field types like Airtable, but you can organize data to match Softr’s supported formats.
**Supported Field Types & Workarounds**
- **Text**: Standard text fields.
- **Number**: Whole numbers, decimals, currency.
- **Date & Time**: Standard date formats. See below for supported formats:
**Supported Date and Time Formats**
Date patterns with month as whole or 3 letter (August, Aug) - Currently only English language is supported.
```plain
MMMM d, yyyy
MMMM dd, yyyy
yyyy MMM d
yyyy MMM dd
dd-MMM-yyy
```
Date patterns with month as numberSupported separators: `-`, `/`, `.`, `space`
```plain
yyyy MM dd
yyyy MM d
yyyy M dd
yyyy M d
MM dd yyyy
MM d yyyy
M dd yyyy
M d yyyy
dd yyyy MM
d yyyy MM
dd yyyy M
d yyyy M
```
Date timeDate part is same (both formats), times
```plain
hh:mm a
hh:mma
hh:mm:ss a
hh:mm:ssa
hh:mm:ss.SSS a
hh:mm:ss.SSSa
h:mm a
h:mma
h:mm:ss a
h:mm:ssa
h:mm:ss.SSS a
h:mm:ss.SSSa
HH:mm
HH:mm:ss
HH:mm:ss.SSS
H:mm
H:mm:ss
H:mm:ss.SSS
HH:mmZ
HH:mm:ssZ
HH:mm:ss.SSSZ
H:mmZ
H:mm:ssZ
H:mm:ss.SSSZ
```
Here are few samples for time
```plain
01:24:41 AM
01:24:41AM
23:24:41
01:24 AM
01:24AM
16:24
01:24:41Z
01:24:41+03:00
```
Date and time combined is`Date format`T`Time format` like
```plain
1994-11-05T08:15:30-05:00
1994-11-05T13:15:30Z
```
- **Checkbox**: Use "true" (checked) or "false" (unchecked).
- **Image, File, Video/Audio**: Store file URLs. If storing multiple image URLs in the same cell, separate them with a comma
- **Tag Field**: Separate multiple values with commas.
- **Rating**: Use integer values from 1 to 5.
- **File Uploads:** Google Sheets doesn’t support direct file uploads. Use URLs instead.
---
# monday.com
Source: https://docs.softr.io/data-sources/mondaycom
monday.com is like a spreadsheet database and work management system that can also act as a relational database. As a result, it is a more robust data management option than simple spreadsheet solutions.
This integration allows you to:
- give your clients real-time project visibility
- collect information faster
- create user-friendly dashboards without board limits
> **Info**
>
> monday.com is available on **Professional** and higher plans.
## **1. Connect your monday.com account**
To use monday.com in Softr, you must first **connect your monday.com account**. Any monday.com account you connect in Softr can be used by all of the workspace's collaborators in all of the workspace’s apps.
> **Warning**
>
> To connect your monday.com data to Softr you will need **admin** access in your monday.com workspace.
1. **Get your API token**
- Go to **Administration** > **Connections** > [API in monday.com.](https://developer.monday.com/api-reference/docs/authentication#admin-tab)
- Copy your **Personal API Token**.

2. **Add monday.com as a data source in Softr**
- Open [Softr’s Integrations page](https://studio.softr.io/dashboard/integrations).
- Click **Connect new**.

- Select **Monday.com** in the list of integrations.

- Paste your Personal API Token in the **Personal API Token** field. Then click **Connect**.

## **2. Connect your monday.com data to your Softr app**
Once your monday.com account is connected, you can use it in any Softr application.
1. **Connect your data to a dynamic block**
To display your data in the app, connect a [dynamic block](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/visualize-data-with-building-blocks/41p6U2eZs7zgY8zWmFV4eH#1859a723d691803d9551ecd7b3b0c043) (e.g. [List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU), [Grid](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/grid-block/42JZoeYwMsogZcveqh74QH), [Table](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/table-block-/j7rGwu7J7zuU69h3bZ7HFe)) to your monday.com board:
1. Go to the block's **Source** tab. In **Account**, select your monday.com account.
2. In **Workspace**, select the workspace you want to connect.
3. In **Board**, pick the board you want to use.
> **Warning**
>
> **Important:** You can connect **only one board to one block**. For example, if you want to show a list of clients, you can select the **Companies** board. If you would like to show **Tickets**, you will need to add another **dynamic block.**

2. **Map monday.com columns to item fields**
When you connect your board to a block, you can choose which monday.com **columns** to display and map it to a Softr field. This lets you control how your monday.com data appears in Softr.
**Example:** If your monday.com board has a **file column** with photos, map it to an **Image** field in Softr so it displays correctly.


_Mapping an image field_

_The Photo image field window with Display type set to Image_
You can learn more about Softr field types in the [List block overview](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU).
### **Supported fields**
Most fields you edit in monday **monday.com** can be edited in Softr, but there are some exceptions:
- **Read-Only Fields:** Some fields can be displayed but **not edited**, including:
- **Created by**
- **Created at**
- **Last updated**
- **Item ID**
- **Mirror fields**
> **Warning**
>
> Currently Formula fields and Progress fields are not supported.
### **Connected boards in monday.com**
Connected Boards let you link data between different boards, making **monday.com a relational database**.
For example, if you have two boards:
- **Clients**
- **Projects**
You can **connect Clients to Projects** to see which projects each client is involved in. This helps keep all related information in one place.

_monday.com Projects board with a Connected board with Clients._
Below, you can see the Clients table, where the Project field is a Connected board that shows records from the Projects table.

_monday.com Clients board with a Connected board with Projects._
### Subitems
[Subitems](https://support.monday.com/hc/en-us/articles/360011905480-All-about-subitems) in monday.com help you add extra layers of information to your board items. You can sync these subitems to your Softr application as a [Linked List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/linked-list/bWjTdKhbftofSEKRSxMFz9).
To do this, ensure you have a page with your Items mapped to any Dynamic [List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU) block, along with a corresponding [List Detail](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/item-details-block-/4bE8XaFbJp45wkAwuWiz8f) page mapped to the same board.
When you add a List block to this page, you’ll have the option to display either **Items** or **Subitems**.
If you choose **Subitems**, only the sub-items will be shown, automatically filtered based on the parent task details in the view. (This filtering applies in both the preview and the published app.)
---
# SmartSuite
Source: https://docs.softr.io/data-sources/smartsuite-
SmartSuite is a spreadsheet-based database and work management system that can also function as a relational database.
This integration allows you to:
- Connect your SmartSuite data to Softr effortlessly
- Display and manage SmartSuite records within your Softr apps
- Utilize relational data for enhanced workflows
> **Info**
>
> SmartSuite is available on all plans, including Free.
## **1. Connect your SmartSuite account**
To use SmartSuite in Softr, you must first **connect your SmartSuite account**. Any SmartSuite data source you add to Softr can be used across all apps within your Softr workspace.
1. **Add SmartSuite as a data source in Softr**
1. In the [Softr Studio dashboard](https://studio.softr.io/dashboard/integrations), click **Integrations** in the left menu.
2. Click **Connect new**.

3. In the **Select an integration** window, click **SmartSuite**.

4. Log in to your **SmartSuite** account (if not already).
5. Authorize Softr to access your SmartSuite data.
Once connected, your SmartSuite data will be available to use in Softr.
## **2. Connect your SmartSuite data to your Softr app**
After connecting SmartSuite, you can use its data in any Softr app.
1. **Connect your data to a dynamic block**
To display your data in the app, connect a [dynamic block](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/visualize-data-with-building-blocks/41p6U2eZs7zgY8zWmFV4eH#1859a723d691803d9551ecd7b3b0c043) (e.g., [List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU), [Grid](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/grid-block/42JZoeYwMsogZcveqh74QH), [Table](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/table-block-/j7rGwu7J7zuU69h3bZ7HFe)) to your SmartSuite table:
1. Open the **Source** tab of the block settings.
2. In **Account**, select your SmartSuite account.
3. In **Workspace**, select the workspace.
4. In **Solution**, select the solution.
5. In **Table**, pick the table you want to use.
> **Warning**
>
> **Important**: Each **block can connect to only one SmartSuite table**. If you need to display data from multiple tables, use separate blocks.

2. **Map SmartSuite fields to item fields in softr**
Each SmartSuite table has multiple fields (columns) with predefined types (e.g., File, Yes/No, Formula). Connecting your table to a block lets you choose which SmartSuite **fields** to display and map it to a Softr field. This lets you control how your SmartSuite data appears in Softr.
**Example:** If your SmartSuite table has a **Photos (Files & Images field)**, map it to an **Image field** in Softr to display it correctly.

_SmartSuite fields_

_Mapping an image field_
> **Info**
>
> Learn more about Softr field types in the [List Block Overview](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU).
### **Supported Fields**
Most editable SmartSuite fields can be modified in Softr, but some computed fields are **read-only**, including:
- **Formula fields**
- **Rollup fields**
- **Lookup fields**
### **Linked Records**
One of SmartSuite’s key features is **Linked Records**, which allows you to create relationships between tables. This makes SmartSuite a **relational database**.
For example, if you have two SmartSuite tables:
- **Tasks**
- **Projects**
You can link the **Tasks table** to the **Projects table** to show which project each task belongs to.
Below, you can see the **Tasks table**, where the **Project field** is a linked record showing data from the **Projects table**.

_SmartSuite table with projects_

_Project linked records_
---
# ClickUp
Source: https://docs.softr.io/data-sources/clickup
ClickUp is a comprehensive project management and productivity tool that you can use to manage projects, clients, tasks, files, and more. Softr supports all Lists within ClickUp. This allows you to:
- Connect your ClickUp data to Softr for a branded app
- Read, write, update, and delete data in ClickUp from within your Softr app
- Share with external parties or larger groups without sacrificing privacy or paying for each access
> **Tip**
>
> ClickUp as a data source is available on Softr’s **Professional** plan and above. It is not available on the Free and Basic plans.
## Connect ClickUp Data to Softr
1. **Add ClickUp as a data source**
In your Softr workspace, click **Integrations** in the left menu.

_Click Integrations in the left menu_
Click **Connect new**.
Click the **ClickUp** tile in the list of data sources.

_Click the ClickUp tile_
In the Connect to ClickUp window, click **Connect**.

_Click Connect in the Connect to ClickUp window_
If you are not signed in to ClickUp, sign in first. Then select the Workspaces you want to connect to Softr and click **Connect Workspace**.

_Select the Workspaces, then click Connect Workspace_
Softr opens again. Your ClickUp connection now appears in the Integrations list and in every Softr app.
To rename, share, re-authenticate, or remove the connection, click the three dots next to it. Select **See active apps** to see which apps use it.

_Click the three dots to rename, share, re-authenticate, or remove the connection_
2. **Connect a block to your new ClickUp datasource**
In any of your Softr apps, select a dynamic block, such as a List block. In the Source settings, select **ClickUp - \[connection name]** as the **Account**.
Then select the **Team**, the **Space**, and the **List** to show.
> **Tip**
>
> You can use any List from ClickUp, whether it is in a folder or not. Softr ignores the hierarchy in ClickUp and shows all Lists in a Space.

_Set the Account, Team, Space, and List in the Source settings of the block._
Hover over a block to see which data sources it supports.

_Hover over a block to see what data sources it supports._
3. **Map your ClickUp properties to the block elements**
Click the block and select the **Content** tab. Map your ClickUp fields to the visual elements of the block.

_Map the ClickUp fields to the block elements in the Content tab_
To map a field, click it and choose the field from ClickUp. For example, map an image element to the **Files** field.

_Map an image element to a file field_
You can add new fields, delete fields, duplicate fields, or change the styling of individual fields and elements. You can also change the field type if it does not match how you want it to display. Read more about mapping data [here](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU#content).
4. **Step 4 (optional): Create app users from ClickUp**
You can sync a list of contacts or people in ClickUp so that they become Users of your Softr app. To learn more about users and how to sync them, check out [this article](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/syncing-users-with-a-data-source/hshRGygHr4T33EnaLntGf9).
## Supported ClickUp Fields
Not all fields are currently supported by Softr, but we’re adding more all the time. Some fields, such as Rollup are not exposed by the ClickUp API and are unretrievable by Softr.
| | | |
| ---------------------------- | ------------------ | ----------------- |
| **Supported** | **Read-Only** | **Not Supported** |
| Number | Formula | Rollup |
| Text | People | |
| Long Text | Tasks | |
| Dropdown | Voting | |
| Date | Location | |
| Text area (Long text) | Users | |
| Money | Date created | |
| Website | Date updated | |
| Email | Creator | |
| Manual Progress | Assignees | |
| Phone | Signature | |
| Relationship | Files | |
| Location | Automatic Progress | |
| Rating | | |
| Translation | | |
| Status | | |
| Start Date | | |
| Due Date | | |
| Points | | |
| Description | | |
| Time Estimate | | |
| Action Items | | |
| Summary | | |
| Progress Updates | | |
| Custom Autofill with AI | | |
| Categorize | | |
| T-Shirt Size | | |
| Sentiment | | |
| Labels | | |
| Name | | |
| Priority | | |
| Checkbox | | |
| Relationship (between lists) | | |
## Softr Support for Tasks in Multiple Lists
ClickUp allows you to show tasks from one list inside other lists. Accessing these multiple lists is also possible in Softr, regardless of which list a task is housed in. For more information about these fields in ClickUp, see [this article](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/syncing-users-with-a-data-source/hshRGygHr4T33EnaLntGf9).
## ClickUp API Rate Limits
ClickUp has Rate limits based on the subscription plan on each Workspace level. This means that the rate at which you can read and interact with data from ClickUp will depend on your ClickUp plan. For API calls to ClickUp these are the current rate limits for ClickUp plans:
- Free Forever, Unlimited, and Business: 100 requests per minute per token.
- Business Plus: 1,000 requests per minute per token.
- Enterprise: 10,000 requests per minute per token.
## FAQ
**Can I use ClickUp data in Softr templates?**
Yes. Each Softr template comes with a sample Airtable base, so you can see how data is structured for the use case (e.g. client portal, inventory management). But you can use templates with another Softr-supported data source (like ClickUp), by connecting your own data. We recommend you follow the data structure in the sample base.
**Can I pull in sub-tasks from ClickUp?**
Currently this is no supported, but we will be adding this soon! In the meantime, you can use our REST API datasource to pull in other resources from ClickUp like sub-tasks, built-in ClickUp comments, and more.
**What is the heirarchy of supported ClickUp objects in Softr?**
Softr can connect one list to one block at a time. The list can be within a folder as well.
---
# Xano
Source: https://docs.softr.io/data-sources/xano
Xano is a powerful backend-as-a-service platform that enables you to build and manage databases, APIs, and business logic without writing code. By integrating Xano with Softr, you can seamlessly use your Xano data in your Softr applications.
This integration allows you to:
- Store and retrieve structured data dynamically
- Use API-driven workflows in your Softr apps
- Securely manage and scale your backend
> **Info**
>
> Xano is available on the Professional, Business, and Enterprise plans.
> **Warning**
>
> **Data Connector** is a Xano add-on that you will need in order to connect Xano to your Softr apps. [Learn more](https://docs.xano.com/database/database-connector)
## **1. Connect Xano to Softr**
To use Xano in Softr, you need to connect your Xano instance as a data source. Note that once connected, all workspaces inside an instance will be available inside your Softr apps.
1. **Open the database connector in Xano**
1. **Log in to Xano** and go to the **server instance** you want to connect.
2. Click the **gear icon** next to the server instance.\

_Click on the gear icon next to the server instance you want to connect to._
3. In the menu on the right, select **Database Connector**.\

_Select the Database Connector option_
2. **Generate your instance’s public IP and credentials**
In order for Softr to be able to access your instance, you’ll need to create a publicly accessible IP address and get some credentials so that only those with the credentials can access it.
1. Click the **GET buttons** to generate:\
- A **public IP address** (required for Softr to access Xano)
- **Access credentials** (used to authenticate Softr)

_Click the GET buttons to generate a public IP and server credentials._
2. **Copy and securely store your credentials**. By default, they are hidden for security reasons. Click **Show credentials**, then copy and save them in a secure location.\

_Click on Show credentials to reveal them_
3. **Allow Softr’s IP addresses in Xano**
1. Go to the **Settings tab** in the Database Connector.
2. Click **+ Add** and enter the following Softr IP addresses:\
- `3.120.79.212`
- `3.123.159.186`
- `52.58.246.121`
3. Click **Save**.\

_Click on the settings tab, add Softr’s IP addresses, then click Save._
4. **Connect Xano in Softr**
1. In the [Softr Studio dashboard](https://studio.softr.io/dashboard/integrations), click **Integrations** in the left menu.
2. Click **Connect new**.\

_The Integrations page, with the Connect new button_
3. In the **Select an integration** window, click **Xano**.\

_The Select an integration window, with Xano selected_
5. **Enter your Xano credentials in Softr**
Note that you have Full Access credentials as well as Read-Only credentials, so make sure to use the correct ones for your use case. We always recommend using the Full Access credentials so you don’t have to re-authenticate later if you expand your Softr apps’ capabilities.
1. Copy and paste your Xano credentials into the appropriate fields in the **Connect to Xano database** window:
- **User**
- **Password**
- **Host**
- **Database**
2. Leave **Port** set to `5432` (default for Xano).
3. Enter a **Name** for your connection (optional). Leave **Environment** set to `live`.\

_Fill in the fields with the parts of your server credentials._
> **Warning**
>
> If you copy your credentials and they paste in as _**xxxxxxxxxxx**_ then you need to unhide them before copying, as explained in Step 3.
6. **Click 'Connect' to complete setup**
Once all fields are correctly filled in, click **Connect** to finalize the connection.

_Click Connect once you’ve pasted in your credentials._
## **2. Connect your Xano data to your Softr app**
Once your Xano account is connected, you can use it in any Softr application.
1. **Connect your data to a dynamic block**
To display your data in the app, connect a [dynamic block](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/visualize-data-with-building-blocks/41p6U2eZs7zgY8zWmFV4eH#1859a723d691803d9551ecd7b3b0c043) (e.g. [List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU), [Grid](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/grid-block/42JZoeYwMsogZcveqh74QH), [Table](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/table-block-/j7rGwu7J7zuU69h3bZ7HFe)) to your Xano table:
1. Open the **Source** tab of the block settings.
2. In **Account**, select your Xano connection.
3. In **Workspace**, select the workspace you want to connect.
4. In **Table**, pick the table you want to use, or select the **Query** tab to add a new query.
5. Optionally, select the **primary field**.\

_Connect Xano table to dynamic block_
2. **Map Xano fields to item fields**
When you connect your table to a block, you can choose which Xano **properties** to display and map to Softr fields. This lets you control how your data appears in Softr.
1. Open the **Content** tab of the block settings.
2. Under **Item fields**, click **Add** and turn on the Xano properties you want to show.
3. Click a field to change how it displays. For example, select **Image** as the display type for an image field.\

_Map Xano fields to item fields_
**Example:** If you have an **email field** in Xano, select **an email field** in Softr.
---
# Supabase
Source: https://docs.softr.io/data-sources/supabase
Supabase is a powerful open-source backend-as-a-service platform that allows you to store, manage, and query your data effortlessly. By integrating Supabase with Softr, you can seamlessly use your Supabase database in your Softr applications.
This integration allows you to:
- Store and retrieve structured data dynamically
- Use real-time updates in your Softr apps
- Securely manage and scale your backend
> **Info**
>
> Supabase is available on **Professional** and higher plans.
## 1. Connect Supabase to Softr
To use Supabase in Softr, you need to connect your Supabase project as a data source.
1. **Select your Supabase project**
1. **Log in to Supabase** and go to the **dashboard**.
2. Click on the **project** you want to connect to Softr.\

_Click on the project you want to connect to Softr_
2. **Configure project settings**
1. Click the **Connect** button at the top of the project settings page.\

_Click on Project settings in the bottom left menu_
2. Change the **Type** to **PSQL**.
3. Open the **View parameters** dropdown under the **Session Pooler** section.\

_Click on the Database tab under Configuration_
3. **Copy your supabase credentials**
1. Locate the **Configuration Parameters** section.
2. Copy and securely store the following credentials:\
- **Host**
- **Database**
- **Port** (default is `5432`)
- **User**
- **Password** (usually the project password)

_Find the Connection parameters section and copy down the credentials_
4. **Set the Pool Size**
Setting the pool size ensures your Supabase database can support multiple connections from Softr at the same time. You set this number to 45 _**or greater**_.
1. Click on Project Settings
2. Click on Database
3. Type in the pool size number (should be 45 or greater)
4. Click Save

5. **Connect Supabase to Softr**
1. **Log in to Softr** and open the [Softr Studio dashboard](https://studio.softr.io/dashboard/integrations). Click **Integrations** in the left menu.
2. Click **Connect new**.

3. In the **Select an integration** window, click **Supabase**.

6. **Enter your Supabase credentials in Softr**
1. Copy and paste your Supabase credentials into the matching fields in Softr:\
- **Host**
- **Port** (`5432` by default)
- **Database**
- **User**
- **Password**
2. Enter a **Name** for your connection. This name is optional.
3. Click **Connect**.

_The Connect to Supabase database window, with the fields to fill in_
7. **Restrict IP Access (Optional)**
If you need to restrict IP addresses inside Supabase, add **Softr’s IP addresses** to your allowed list:
- `3.120.79.212`
- `3.123.159.186`
- `52.58.246.121`
## 2. Connect your Supabase data to your Softr app
Once your Supabase account is connected, you can use it in any Softr application.
1. **Connect your data to a dynamic block**
To display your data in the app, connect a [dynamic block](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/visualize-data-with-building-blocks/41p6U2eZs7zgY8zWmFV4eH#1859a723d691803d9551ecd7b3b0c043) (e.g. [List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU), [Grid](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/grid-block/42JZoeYwMsogZcveqh74QH), [Table](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/table-block-/j7rGwu7J7zuU69h3bZ7HFe)) to your Supabase table:
1. Go to the Block **source** **tab** and select your Supabase integration.
2. Select the **database** and **schema** you want to connect.
3. Pick the **table** you want to use or **add a new** **query**
4. Optionally, select the **primary field**.

2. **Map Supabase fields to item fields**
When you connect your table to a block, you can choose which Supabase **properties** to display and map to a Softr field. This lets you control how your data appears in Softr.
**Example:** If you have an **email** column in Supabase, show it as an **Email** field in Softr. If a column holds image URLs, such as **Avatar URL**, show it as an **Image** field.

---
# BigQuery
Source: https://docs.softr.io/data-sources/bigquery
BigQuery is a powerful cloud-based data warehouse that enables you to analyze massive datasets quickly. WithSoftr’s BigQuery integration, you can build custom dashboards, reports, and even full-fledged apps tailored to your business needs.
This integration allows you to:
- Create **real-time dashboards** and reports
- Run **custom SQL queries** for deeper insights
- Securely **control access** to data
- Share **data-driven insights** with partners and stakeholders
> **Info**
>
> BigQuery is available on Business and Enterprise plans.
> **Warning**
>
> **Important**: **BigQuery is read-only**, so you can’t add, update, or delete data via Softr. This makes blocks like Forms unusable, and you can’t manage or store Softr user data in BigQuery. However, you can still manage user data within Softr.
**Example Use Cases:**
- **Dashboards** – Track **user activity, app performance, and sales trends** in a single dashboard without complex analytics tools.
- **Partner Insights** – Share **product performance data** with vendors using secure, real-time BigQuery dashboards.
## **1. Connect BigQuery to Softr**
To use BigQuery in Softr, you must first **link your account**. Before connecting BigQuery to Softr, make sure you have:
- A **Google Cloud Platform** project with **BigQuery enabled**
- A **dataset** within your BigQuery project
- At least **read-only access** for Softr to your BigQuery dataset
1. **Open data Ssurces in Softr**
1. Navigate to **Data Sources** in your [**Softr Dashboard**](https://studio.softr.io/dashboard/data-sources).
2. Click **Connect Data Source**.

_Add, edit, or remove a datasource using the buttons on the dashboard_
2. **Authenticate BigQuery**
1. Select **BigQuery** from the list of available data sources.
2. Follow the on-screen prompts to authenticate with **Google OAuth**.
3. **Grant Softr the necessary read-only permissions** to your BigQuery datasets.
## **2. Connect your BigQuery data to the Softr app**
Once connected, you can use your BigQuery data to build dashboards and display records in your Softr apps.
1. **Connect your data to a dynamic block**
To display your data in the app, connect a [dynamic block](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/visualize-data-with-building-blocks/41p6U2eZs7zgY8zWmFV4eH#1859a723d691803d9551ecd7b3b0c043) (e.g. [List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU), Chart) to your BiqQuery table:
1. Go to the Block **source** **tab** and select your BigQuery integration.
2. Select the **project** and **dataset** you want to connect.
3. Pick the **table** you want to use or **create a new** **query**
4. Optionally, select the **primary field**.\

_Connect BigQuery to a dynamic block_
2. **Map BigQuery fields to Softr fields**
When you connect your table to a block, you can choose which BigQuery **properties** to display and map to a Softr field. This lets you control how your data appears in Softr.
**Example:** If you have a **date** in BigQuery, map it to **grouping** in Softr.

_Mapping fields from BigQuery to Softr_
### **Custom SQL Queries (Optional)**
You can use **Softr’s built-in query editor** to write SQL queries directly against your BigQuery dataset for advanced data analysis.
1. Write and run **custom queries** inside Softr.
2. Connect query results to **dynamic blocks** to display **custom tables and visualizations**.
## **Troubleshooting**
If you encounter errors while connecting BigQuery to Softr, check for these common issues:
### **Error: Something went wrong “Access Denied”**

_Important part of error in text: 'Access Denied:
BigQuery BigQuery: Permission denied while globbing file pattern.',_

_Important part of error in text: 'Access Denied:
BigQuery BigQuery: Permission denied while getting Drive credentials.',_
**Cause:** BigQuery **external tables** (from Google Drive, Sheets, or Cloud Storage) require additional permissions that Softr does not request.
**Internal vs external tables**
In BigQuery, while creating a table in some cases user can decide or has only the option to create an external datasource.

_user might have the option to or be forced to create an “external table”. Table creation dialog, BigQuery console._
External tables are forced or available when a user creates a table from:
- A file on Google Drive with supported format (CSV, Avro, …)
- A Google Sheet document
- A file on Google Cloud Storage
If the user goes for an external table in these cases, trying to integrate such a table with Softr will give them an error message similar to those mentioned above.
To identify an existing table as either internal or external, one could take a look at table details and would see an “External data configuration” section for external tables similar to the following:

**Solution 1: Use a Native Table**
To avoid issues, set the table type to **Native Table** when creating it (if available).
> **Warning**
>
> **Note:** A Native Table **won’t sync** with the original source, so any updates to the external source **won’t be reflected** in Softr.
**Solution 2: Copy the External Table**
If using a Native Table isn’t an option, create a **duplicate** of the external table as a new **Native Table** and use that in Softr.
📌 **SQL Example:**
```sql
sql
CopyEdit
CREATE TABLE native_table_copy AS
SELECT * FROM external_table;
```
> **Warning**
>
> **Downside:** This method **duplicates data**, which may increase storage costs.
### Error: Google BigQuery does not stay connected to Softr
This issue is caused by the Reauthentication Policy settings in Google Admin console.
To resolve things you can:
Set Softr as a Trusted App and then exempt Trusted Apps from reauthentication.\
Alternatively, you can change the settings to never require reauthentication for any app.
See this link () for more details on this. Once you have changed your settings in Google Admin, please reconnect your Google account with Softr.
---
# SQL Database
Source: https://docs.softr.io/data-sources/sql-database
In Softr, you can build data-driven apps with **PostgreSQL, MySQL, SQL Server, and MariaDB** as data sources.
With SQL data sources, you can:
- Show your structured data in **custom apps and dashboards**
- Enable **secure access** for internal teams and external partners
- Scale without hitting **record limitations**
> **Info**
>
> SQL data sources are available on Business and Enterprise plans.
## **1. Connect your SQL database to Softr**
Before you connect, make sure you have:
- Your **SQL database credentials**: host, port, database name, user, and password.
- Permission to access the database.
1. **Open Integrations**
1. In the [Softr Studio dashboard](https://studio.softr.io/dashboard/integrations), click **Integrations** in the left menu.
2. Click **Connect new**.

3. In the **Select an integration** window, click **PostgreSQL**, **MySQL**, **SQL Server**, or **MariaDB**.

_The Select an integration window with PostgreSQL selected_
2. **Enter your database credentials**
The connect window asks for these fields:
- **Name**: A name that helps you recognize the connection in Softr.
- **Host**: The database server address, for example `db.example.com`.
- **Port**: The port your server uses. Softr fills in the default port for the database type: `5432` for PostgreSQL, `3306` for MySQL and MariaDB, and `1433` for SQL Server.
- **Database**: The name of your database.
- **User**: Your database username.
- **Password**: Your database password.

_The Connect to PostgreSQL database window_
3. **Confirm your setup**
Click **Connect** to verify and establish the connection. If the connection fails, check your credentials and try again.
## **2. Connect your SQL data to your Softr app**
Once your SQL account is connected, you can use it in any Softr application.
1. **Connect your data to a dynamic block**
To display your data in the app, connect a [dynamic block](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/visualize-data-with-building-blocks/41p6U2eZs7zgY8zWmFV4eH#1859a723d691803d9551ecd7b3b0c043) (for example, [List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU), [Grid](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/grid-block/42JZoeYwMsogZcveqh74QH), or [Table](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/table-block-/j7rGwu7J7zuU69h3bZ7HFe)) to your SQL table:
1. Go to the block **Source** tab and select your SQL account in **Account**.
2. Select the **database** you want to use.
3. For PostgreSQL and SQL Server, select the **schema**. MySQL and MariaDB have no schema field.
4. Select the **table** you want to use, or add a new **query**.
5. Optionally, select the **primary field**.

_The Source tab of a List block connected to a PostgreSQL table_
2. **Map Fields**
When you connect your table to a block, you can choose which table **properties** to display and map to Softr fields. This lets you control how your data appears in Softr.
**Example:** If you have an **email field** in the SQL database, select **an email field** in Softr.

_Mapping an image field_
### **Restricting IP Access**
If needed, add Softr’s IPs to your database’s **allowed list**:
- `3.120.79.212`
- `3.123.159.186`
- `52.58.246.121`
## **FAQs**
**Can I update my SQL database from Softr?**
Yes! You can create forms in Softr that **write data back** to your SQL database.
**Is my SQL data secure?**
Absolutely! Softr uses **industry-standard encryption** to protect your data.
**Can I connect multiple databases to one Softr app?**
Yes! You can connect **multiple SQL databases** and use them within the same app.
March 7, 2025
---
# Rest API
Source: https://docs.softr.io/data-sources/rest-api
Softr’s **REST API data source** allows you to connect to almost any platform, database, or service. If Softr doesn’t natively support your data source, you can likely still integrate it using the **REST API connector**.
With the REST API connector, you can:
- Import **real estate listings from Zillow, inventory from Shopify, or invoices from Stripe**
- Connect to **public APIs** (for example, APIsList, Public APIs, or RapidAPI)
- Integrate **new CRMs and productivity tools**
- Fetch and create data using any **standard HTTP REST API**
> **Info**
>
> Rest API is available on all plans, including Free.
> **Tip**
>
> REST API is not a supported data source for the [Users](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/syncing-users-with-a-data-source/hshRGygHr4T33EnaLntGf9) of your application.
## **1. Connect a REST API to Softr**
You connect a REST API once per workspace. Then you can use it in all your apps.
1. **Open Integrations**
1. In the Softr Studio dashboard, click **Integrations** in the left menu.
2. Click **Connect new**.

3. In the **Select an integration** window, click **Rest API**.

2. **Connect your account**
Fill in the **Connect your account** window:
1. **Provider**: Enter a name for the API, for example "Stripe". You'll see this name in your list of integrations.
2. **Authentication type**: Select **API key** or **OAuth**. The API's own documentation tells you which one it uses.
3. **Base URL**: Enter the root address of the API, for example `https://api.stripe.com`. The base URL is optional. The Vibe Coding block needs it.
4. Fill in the fields of your authentication type (see below).
5. Click **Continue**.

**API key**
- Select **Bearer token** when the API expects `Authorization: Bearer `. Then paste the key in **API key**.
- Select **Custom header** when the API expects the key in another header. Enter the header name in **Header**, then paste the key in **API key**.
The blue box shows the exact header that Softr sends with every request.
**OAuth**
1. Copy the **OAuth Redirect URL** and add it to the OAuth app settings of the API.
2. Enter the **Authorization URL**, the **Access token URL**, the **Client ID**, the **Client secret**, and the **Scopes** from the API's documentation.
3. Click **Continue**, then sign in to the API in the window that opens.

**OAuth advanced settings**
Some APIs need extra parameters in the OAuth requests. The API's documentation lists them. To add them, turn on **Advanced settings** before you click **Continue**. Then click **Add Parameter** in the group that the API names:
- **Authorize parameters**: Softr adds them to the authorization URL, where the person signs in.
- **Access token parameters**: Softr sends them when it gets the first access token.
- **Refresh token parameters**: Softr sends them when it refreshes an expired access token.
For example, Google returns a refresh token only when the authorization URL has `access_type=offline` and `prompt=consent`. Without a refresh token, the connection stops working when the first access token expires.

> **Warning**
>
> **Important**: Each API works differently. This page shows how Softr's REST API connection works. It isn't a step-by-step guide for one specific API.
>
> If you need help with an API beyond the scope of this page, reach out to one of our [Certified Softr Experts](https://www.softr.io/softr-experts). They can guide you or build it for you.
3. **Add API resources (endpoints)**
A resource is one API call that you save and reuse in your apps, for example "Invoices" or "Customers by email". Resources support the **GET** and **POST** methods.
1. On the **Integrations** page, click the **...** menu of your REST API integration.
2. Click **Edit resources**.

3. In the **Resources** window, click **Add**.

> **Tip**
>
> You can also add a resource from a block. In the block's **Source** tab, open the **Resource** dropdown and click **Add resource**.
4. Fill in the resource:
- **Name**: A name that helps you find the resource in the list.
- **HTTP method**: **GET** for most endpoints. Select **POST** only when the API's documentation uses POST to return data (see [Body](#body)).
- **URL**: The endpoint that Softr calls, for example `https://api.stripe.com/v1/invoices`.
5. Click **Execute** to send a test request to the API.

6. When the test request succeeds, click **Save**.
> **Info**
>
> Softr saves a resource only after a successful **Execute**. When you change the request (URL, headers, URL params, placeholders, body, or pagination), click **Execute** again.
> **Tip**
>
> You'll often need the optional sections and the schema too. Read the sections below before you save.
## **2. Configure the optional sections**
Below the **Execute** button, the resource has more sections. Turn on a section with its toggle. Every API is different, so you may need all of these sections or none of them. Check the API's documentation.
### **Headers**
The **Headers** section always shows the authentication header of the integration. Click **Add** to add a header that only this resource needs.

### **URL params**
Use **URL params** to add query parameters to the URL. Add each parameter as a name and a value. You can also type them in the URL field, but this section keeps them easier to read and change.
Find the parameter names and values in the API's documentation. In the example above, the `customer` parameter tells the Stripe invoices endpoint to return the invoices of one customer:

A parameter value can be static or dynamic. The customer changes with the person who is logged in. Thus the example uses the placeholder `{LOGGED_IN_USER:StripeID}`. Softr replaces it with the `StripeID` field of the logged-in user.
### **Placeholders**
Placeholders send dynamic data to the API, based on the logged-in user, the page, or the filters and search of a block. Write a placeholder in curly braces, for example `{placeholderName}`, in the URL, the URL params, or the body. Softr doesn't replace placeholders in headers.
You can use four kinds of dynamic placeholders:
- `{LOGGED_IN_USER:}`: Sends a field of the logged-in user. `{LOGGED_IN_USER:EMAIL}` and `{LOGGED_IN_USER:NAME}` send the email and the name of the user.
- `{recordId}`: Sends the ID of the record that the page shows (the `recordId` in the page URL).
- `{URL_PARAM:}`: Sends the value of a parameter in the page URL.
- `{filter.}`: Sends the value of a search or filter in a block.
When a request has placeholders, the **Placeholders** section lists them. Enter a sample value for each one, so that **Execute** can test the request. Your live app doesn't use these sample values.

Use a `{filter.}` placeholder to filter or search the API from a block. In the example below, the **Customers by email** resource sends the search text to Stripe in the `email` URL param. When the block has no search or filter value, Softr removes a URL param whose value is only a filter placeholder, so the API returns all the records.

_Use the filter placeholder to filter by dynamic values against the API._
Then turn on the search bar of the block in its **Content** tab:

_Turn on the search bar of the block so that people can search the API._
> **Tip**
>
> Softr treats anything inside `{}` as a placeholder.
>
> `{LOGGED_IN_USER:}` sends data of the logged-in user in the API request.\
>
> `{filter.}` filters by a dynamic value, if the API supports it.\
>
> `{recordId}` sends the current record in the API request.\
>
> `{URL_PARAM:}` sends a parameter of the page URL in the API request.
### **Body**
The **Body** section shows when the HTTP method is **POST**. Some APIs use POST to return data, for example search endpoints, GraphQL APIs, or previews. Write the body as JSON. Use the API's documentation to know which keys to send.
In this example, the **Upcoming invoice** resource gets a preview of the next Stripe invoice of the logged-in user:

> **Warning**
>
> A REST API data source is read-only. Softr calls a resource each time a block loads its data, so never use a resource to create, change, or delete data. To send data to an API, use the [Call API](/actions/call-api) action on a block button, or the **Call API** action in [Softr Workflows](/workflows/workflows).
### **Pagination**
Most APIs return a limited number of records per request. Use the **Pagination** section to tell Softr how to get the next page of results. Softr uses cursor pagination:
- **Response parameter - cursor**: Where the cursor of the next page is in the response (**Body** or **Header**), and its name. Turn on **Transformer function** if you need JavaScript to read the cursor.
- **Request parameter - cursor**: Where Softr sends the cursor in the next request, and the parameter name.
- **Request parameter - limit**: The parameter that sets the number of records per page, and its value.
In the Stripe example, Softr sends the ID of the last invoice as `starting_after`, and asks for 25 invoices per page with `limit`.

### **Transformer**
Use the **Transformer** section to change the API response with JavaScript. A transformer can extract a nested list from the response, or calculate a new field. AI tools are good at writing these functions.
In the Stripe example, `return response.data;` keeps only the list of invoices in the `data` key of the response.

## 3. Check the response and the schema
When you click **Execute** and the request succeeds, three tabs show below the sections: **Schema**, **Transformed JSON**, and **Raw JSON**. Scroll down to see them.
**Schema**
The **Schema** tab lists the fields of the response. Softr Studio shows these fields when you set up a block. Each field has four settings:
1. **Key**: The name of the field in the response.
2. **Type**: How Softr shows and filters the field. The types are TEXT, NUMBER, BOOLEAN, DATE, DATETIME, TIMESTAMP, OBJECT, ARRAY, EMAIL, and URL.
3. **Enabled**: Clear this checkbox to hide the field in Softr Studio.
4. **Is ID field**: Turn on this toggle for the field that identifies each record. When no field is the ID field, Softr shows a warning.

**Transformed JSON**
The **Transformed JSON** tab shows the response after your transformer runs. The **Schema** tab is built from this JSON.

**Raw JSON**
The **Raw JSON** tab shows the response exactly as the API sent it. Check this tab first: it shows which transformer you need, if any. In the Stripe example, the invoices are in the `data` key, so the transformer returns `response.data`.

## **FAQs**
**Can I use REST API to update data in Softr?**
No. A REST API data source is read-only: blocks can show its data, but the **Add record** and **Edit record** buttons aren't available. To send data to an API, use the [Call API](/actions/call-api) action on a block button, or the **Call API** action in [Softr Workflows](/workflows/workflows).
**How do I add authentication for my API?**
Select **API key** or **OAuth** when you connect the API. Softr adds the authentication header to every request.
**Can I connect multiple APIs to one Softr app?**
Yes! You can add multiple REST API connections and use them across different blocks.
---
# Snowflake
Source: https://docs.softr.io/data-sources/snowflake
Snowflake is a cloud data platform that stores and queries large analytical datasets. Connecting it to Softr lets you build dashboards, reports and internal tools on top of warehouse data, without exporting it anywhere first.
You connect Snowflake once at the workspace level, then point individual blocks at the tables you want to show.
> **Note**
>
> Softr authenticates to Snowflake with a [programmatic access token](https://docs.snowflake.com/en/user-guide/programmatic-access-tokens), not a password. You generate the token in Snowsight and paste it into Softr.
## Before you start
Have these ready from your Snowflake account:
- Your **account identifier**, in `orgname-account_name` form — for example `myorg-myaccount`. To find it in Snowsight, open the account selector and choose **View account details**. See Snowflake's [account identifiers](https://docs.snowflake.com/en/user-guide/admin-account-identifier) reference if yours is in the older account-locator format.
- The **user** Softr should authenticate as.
- A **programmatic access token** for that user. In Snowsight, go to **Governance & security → Users & roles**, select the user, open **Programmatic access tokens** and choose **Generate new token**. Tokens expire after a maximum of 365 days, and your admin may have shortened that with an authentication policy.
- A **network policy** that permits the connection. Snowflake requires one to _use_ a token, and requires one up front for service users. Your Snowflake admin can attach it to the account or to the single user — see [network policy requirements](https://docs.snowflake.com/en/user-guide/programmatic-access-tokens).
> **Tip**
>
> Give Softr a dedicated Snowflake user with read-only access to just the warehouse, role and database you intend to expose. It keeps the token's blast radius small, makes it easy to revoke, and lets you scope the network policy to that one user.
## Connect Snowflake to Softr
1. **Open Integrations**
In the Softr dashboard, select **Integrations** in the left sidebar, then click **Connect new**.

_The Integrations page, where all external data sources are managed._
2. **Choose Snowflake**
Pick **Snowflake** from the **Select an integration** list.

_Snowflake in the integration picker._
3. **Enter your connection details**
Fill in the connection form:
| Field | Required | What to enter |
| ------------------------- | -------- | ------------------------------------------------------- |
| Name | Yes | A label for this connection inside Softr. |
| Account identifier | Yes | Your Snowflake account, in `orgname-account_name` form. |
| Warehouse | No | The warehouse to run queries against. |
| Role | No | The role Softr should assume. |
| Database | No | The database to scope the connection to. |
| User | Yes | The Snowflake user Softr authenticates as. |
| Programmatic access token | Yes | The token you generated in Snowsight. |
Leaving **Warehouse**, **Role** and **Database** empty uses the defaults configured for the user in Snowflake.

_The Snowflake connection form. User and Programmatic access token are both required._
4. **Connect**
Click **Connect**. The button stays disabled until every required field is filled. Once the connection succeeds, Snowflake appears in your Integrations list and is available to blocks across your apps.
## Show Snowflake data in your app
1. **Point a block at a Snowflake table**
Add a dynamic block — a List, Table or Chart — then open its **Block source** tab and select your Snowflake connection. Choose the database, schema and table you want to display.
2. **Map fields**
Choose which Snowflake columns map to which fields in the block, the same way you would for any other data source. See [Visualize data with building blocks](/core-concepts-overview/visualize-data-with-building-blocks) for the mapping options each block type offers.
## Troubleshooting
**Authentication fails with a valid token**
The usual cause is a missing network policy. Snowflake requires one before a programmatic access token can be used, and requires one up front for service users. Ask your Snowflake admin to confirm a policy is attached to the account or to the user Softr connects as.
Also check the token has not expired — 365 days is the maximum, and an authentication policy can shorten it.
**The connection succeeds but no tables appear**
If you left **Warehouse**, **Role** or **Database** empty, Softr falls back to the user's defaults in Snowflake. If that user has no default warehouse or role, set them explicitly on the connection.
**The account identifier is rejected**
Softr expects the `orgname-account_name` form, not the legacy account locator and not a full URL. Open the account selector in Snowsight and choose **View account details** to read the current identifier.
## Related
[**Choosing a data source**](/data-sources/choosing-a-data-source)
Compare Snowflake against the other data sources Softr supports.
[**BigQuery**](/data-sources/bigquery)
Another warehouse integration, with a similar dashboard-first setup.
[**SQL Database**](/data-sources/sql-database)
Connect PostgreSQL, MySQL, SQL Server or MariaDB.
[**Snowflake documentation**](https://docs.snowflake.com/en/user-guide/programmatic-access-tokens)
Snowflake's own reference for tokens, account identifiers and network policies.
---
# Choosing a Data Source
Source: https://docs.softr.io/data-sources/choosing-a-data-source
## Choosing a data source
The best data source for your Softr application depends on where your data lives and how you plan to scale. If you're starting from scratch and don't have a database yet, we highly recommend using **Softr Databases**. It’s built directly into the Softr Studio, has no API rate limits, and is included in your subscription.

_A Projects table in Softr Databases, inside the Softr Studio._
If you already have your data elsewhere, you have a few options:
- **Migrating to Softr Databases**: If your data is currently in a spreadsheet or Airtable, you might consider moving it into Softr Databases for better performance and easier management. We offer a **one-click migration tool for Airtable** that copies your entire base, and you can easily **import CSV files** from any spreadsheet.
- **Connecting your current source**: If you prefer to keep your data where it is, Softr connects natively to over 20 different data sources. This is a great option if you already have complex workflows or other tools connected to your data.

_Three ways to bring data into a Softr app._
To move an existing Airtable base, follow [Migrating from Airtable to Softr DB](/migration-tips/migrating-from-airtable-to-softr-databases).
When evaluating which path to take, consider the following factors:
- Number of records
- Number of concurrent users
- Data source security
- Technical skill
- Price
Let’s look at each of these in a bit more detail.
### Number of records
Softr can scale to any number of records you need to bring in and display, however there are two things that will determine how many records you can use with Softr - your Softr subscription plan and the data source you are using. Softr categorizes data sources into two camps - Basic (like Airtable and Sheets) and Advanced (like SQL and BigQuery). **Softr Databases** sits in a unique position, offering high record limits (often 1 million+) while remaining as simple to use as basic sources.
Additionally, each of these data sources may also have their own limits on the number of records or rows you can have, which Softr is also bound by depending on your account limits with those providers. If you’re building an app that uses record-heavy databases like messaging, notifications, or have lots of users, you’ll want to take this into consideration. Using **Softr Databases** ensures you are only bound by your Softr plan limits.
### Number of concurrent users
Concurrent users are much more important than the total number of users in an app, because concurrent users are the number of users who will be using the app at the _same time_. Softr uses a data source API/connection directly in realtime. These data sources often limit how often you can get data from their service - this is called rate limiting. Rate limiting varies by data source and can affect how quickly Softr is allowed to fetch data from your data source.
**Softr Databases** is native to the platform and not bound by any external API rate limits, making it a great choice for apps that expect high traffic.
In terms of users, you may have 50,000 users in total, but only 200 are using it at any given time - Airtable or Sheets would be a great datasource for you. However, with apps with tens of thousands of concurrent users, you will definitely want to be using **Softr Databases**, SQL, Supabase, Xano, or another more scalable data source for your app. Every user in your app is fetching data from your data source. The more dynamic blocks, users, and actions you have in your app, the higher the rate limit your data source needs.
### Data source security
Softr does not store or sync data from your data source, although we employ 24 hour caching to ensure your app remains speedy. We rely on connecting to a data source directly and pulling or pushing data at the time of need. Because of this, you should take into consideration a data source’s policies around storage, caching, deletion, encryption, and AI modeling before using it as a data source for your Softr app. If you need a HIPAA compliant data source, the data source itself needs to support it. If you require the data to be encrypted at rest, you need to make sure the data source itself does this.
Since Softr does proxy requests through our servers and store your data source credentials, we make available all of our security policies on our [Security](https://www.softr.io/security) page. Softr is also SOC2 Type II compliant and we provide a standard vendor risk assessment form as well (VRA) - please contact us via the support chat on our website to request more information.
### Technical skill
While Softr is quite easy to use, the data source you connect to is not always as simple. The data source you choose should match the skill level of the app builder. Simple data sources like **Softr Databases**, Airtable, Sheets, Smartsuite, Hubspot, and Monday are much less technical than Supabase, Xano, SQL, or REST APIs. If you feel that you need a highly scalable, but more technical data source and don’t have the skills, we have numerous [Softr Certified Partners](https://www.softr.io/partners) who would be glad to help you build what you need!
### Price
When choosing a data source, you will likely also be evaluating the cost differences between the various services. You’ll want to use the above criteria to help you determine the scope and needs of your app, then find a data source with a plan structure and price that works for you.
## Data source comparison
Below you will find a table of estimated (albeit subjective) comparison of different data sources and their strengths and weaknesses. Note that we don’t track a data source’s own plans and features so always verify for yourself. The table is what we at Softr have seen work as median results when used in Softr apps.
> **Warning**
>
> This is not a representation of plan limits on these services, but rather an indication of acceptable performance on a Softr app running on these data sources.
| | | | | | |
| -------------------------------------------- | --------------------- | -------------------------------- | ----------------- | ------------------- | --------- |
| **Data Source** | **Number of Records** | **Recommended Concurrent Users** | **Data security** | **Technical skill** | **Price** |
| Softr Databases | 1 million + | Unlimited | Medium | Low | $ |
| Airtable | Up to 500,000 | 200-300 | Medium | Low | $$ |
| Google Sheets | 1 million + | 50-100 | Low | Low | $ |
| Smartsuite | Up to 500,000 | 200-300 | Medium | Low | $$ |
| Hubspot | 1 million + | 500-1000 | Medium | Medium | $$$ |
| Salesforce | 1 million + | 500-1000 | High | Medium | $$$$ |
| Monday | Up to 500,000 | 50-100 | Low | Low | $$ |
| Xano | Unlimited | Unlimited | High | High | $$ |
| SQL (PostgreSQL, MySQL, SQL Server, MariaDB) | Unlimited | Unlimited | High | High | $ |
| Supabase | Unlimited | Unlimited | High | High | $ |
| REST API | Unlimited | N/A | Varies | High | Varies |
| BigQuery | Unlimited | N/A | Low | Medium | $ |
| Notion | 1 million + | 50-100 | Medium | Low | $ |
| ClickUp | Up to 500,000 | 50-100 | Medium | Low | $$ |
| Coda | 1 million + | 200-300 | Medium | Low | $ |
| Snowflake | Unlimited | N/A | High | High | $$$ |
| Microsoft Excel | Up to 500,000 | 50-100 | Low | Low | $ |
| Zoho CRM | 1 million + | 200-300 | Medium | Medium | $$ |
| Baserow | Up to 500,000 | 200-300 | Medium | Low | $ |
> **Note**
>
> **Softr Databases** is the only option in the table that pairs unlimited concurrent users with low technical skill. It is native to the platform, so no external API rate limit throttles your app. Each external source gives up at least one of these. Spreadsheets and project tools cap out on concurrency. Warehouses and SQL need technical setup. CRMs get expensive quickly. If your data does not already live somewhere, [start with Softr Databases](/softr-databases/softr-databases-overview).
---
# How to migrate from Airtable to Softr
Source: https://docs.softr.io/migration-tips/migrating-from-airtable-to-softr-databases
Softr gives you two ways to move off Airtable, both from **Migrate from Airtable** in the left sidebar of Softr Studio. Pick the one that matches your setup:
[**Migrate your data and automations**](#migrate-your-data-and-automations)
You have an Airtable base and want its tables, records, and automations in Softr Databases. Start here if you don't have a Softr app yet, or plan to build a new one.
[**Migrate an existing Softr app**](#migrate-an-existing-softr-app)
You already have a classic Softr app, created before November 2026, that reads from Airtable. Softr imports the data and gives you a copy of the app connected to it.
> **Note**
>
> Both paths **copy** your data. Your Airtable base is never modified or deleted, so you can migrate at your own pace and keep Airtable running until you're confident everything works.
## Why switch to Softr Databases
**Built to run operations at scale**
Airtable performance can degrade as record counts, formulas, and linked data grow. Softr Databases are designed to manage data and power apps at scale, so systems stay fast and reliable as operations expand.
**Scale without API limits**
Softr Databases are native to the platform, so there are no external API rate limits throttling your app as your data and traffic grow. Record and storage limits scale with your plan.
**Real business apps, not just data views**
When you need logins, user roles, granular permissions, workflows, and flexible design, Softr gives you everything you need to turn your data into custom business apps.
**No per-seat pricing or hidden costs**
Airtable charges per seat and has strict record limits, even on its high-tier plans. Softr offers generous user and record limits without per-seat costs, which makes it easy to share apps across teams and clients.
**Smarter AI Agents**
[Database AI Agents](/softr-databases/ai-agents) can trigger on record creation, on specific field updates, and on custom conditions, a level of control that isn't available with external sources.
**Your automations come with you**
Airtable automations import as Softr workflows, which connect to tools like Slack, Gmail, HubSpot, QuickBooks, and DocuSign.
## Before you start
A few minutes of prep saves a lot of rework later, whichever path you take.
**1. Rehearse on a copy**
If your base is large or business-critical, duplicate it in Airtable with a small amount of data and run the import on that first.
**2. Clean up in Airtable first**
The import brings your base across as it is. Merging duplicate tables, removing fields you no longer use, and fixing field types is easier before you migrate than after. See [Lessons from a real migration](#lessons-from-a-real-migration).
**3. Check your Airtable API allowance**
Softr reads your base through Airtable's API, so every migration uses your Airtable plan's API calls. If your Airtable account has hit its API limit, the import can't read the base and stops. Larger bases also take longer to import.
**4. Know what needs a second look**
Most fields, including linked records, attachments, and formulas, come across automatically. A few behave differently in Softr. See [What transfers, and what to double-check](#what-transfers-and-what-to-double-check).
### Lessons from a real migration
Base Flows, the Softr agency that moved [Child's Play Charity](https://www.softr.io/customer-stories/childs-play-charity) off Airtable, migrated 4,000+ records in three weeks. These are the lessons from that project, and most of them are decisions you make before you import anything.
- **Consolidate redundant tables first.** Merging separate tables that hold the same entity into one is usually the single biggest fix for duplicate records.
- **Dedupe before the migration, not after.** Match suspected duplicates against a unique identifier, such as a tax ID or an account number, before anyone touches the new database. Names alone are misleading.
- **Fix field types on the way in.** Numbers stored as text in Airtable will break rollups, sorting, and formulas once they're live.
- **Freeze, don't sync.** A short data freeze with a manual catch-up list is simpler and safer than running a temporary Airtable-to-Softr sync.
## Migrate your data and automations
Use this path to move an Airtable base into Softr Databases. Softr creates a new database with a copy of your tables, fields, and records, and brings your Airtable automations across as Softr workflows.
> **Tip**
>
> Already have a classic Softr app on this base? Use [Migrate an existing Softr app](#migrate-an-existing-softr-app) instead. It runs the same import and reconnects a copy of your app for you, so you don't have to re-point blocks by hand.
### Import your Airtable base
1. **Open Migrate from Airtable**
In Softr Studio, click **Migrate from Airtable** in the left sidebar. On the **Import base** tab, click **Import base**.

_Migrate from Airtable in the left sidebar, and the Import base button._
> **Note**
>
> You can also start an import from **All projects** > **Databases**: click **Create** > **Database**, choose **Import**, select **Airtable**, and click **Continue**.
2. **Choose your Airtable account and base**
In the **Select data to import** dialog, pick a connected Airtable account under **Account**, or choose **Connect new account** to add one. Then select the base under **Base**. The whole base is imported, along with any automations Softr finds in it.

_The Select data to import dialog, with an Airtable base selected._
> **Note**
>
> Don't see your base? Open the **Base** dropdown and click **Edit bases Softr can access**, then give Softr access to the base in Airtable. Choosing **all current and future bases** avoids having to do this again later.
3. **Start the import**
Click **Start import**. The base appears in the **Import base** list with the status **Importing**. Larger bases take longer, so give it a moment to finish.
4. **Review the new database**
When the import finishes, open the new database and work through the review checklist. It lists anything that didn't carry over exactly, how to fix each item, and links to the field in Airtable. Then spot-check record counts, linked records, and attachments.
**The import failed**
A failed import shows **Failed** in the **Import base** list. Hover the retry icon in that row to see why, then click it to try again once you've fixed the cause.
- **This base could not be read - check that the Airtable connection still has access to it.** Check that the base still exists and that Softr has access to it (see the note in step 2). This also happens when your Airtable account has used up its API calls; wait for the allowance to reset or upgrade your Airtable plan, then retry.
- **Could not read this Airtable account's bases. The connection is no longer authorised or its token could not be refreshed.** Reconnect the Airtable account from **Integrations**, then try again.
For other Airtable errors, see [Troubleshooting Airtable Errors](/troubleshooting/troubleshooting-airtable-errors) and [Airtable API call limit exceeded](/troubleshooting/troubleshooting-airtable-api-call-limit-exceeded).
### What transfers, and what to double-check
Most Airtable fields map to an equivalent Softr field and keep their values and settings. The fields below need a closer look after the import, and most of them appear in the review checklist.
| Airtable field | In Softr | What to check |
| ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Single line text, Long text, Number, Currency, Percent, Duration, Email, Phone, URL, Attachment, Autonumber | Matching [field type](/softr-databases/field-types) | Nothing. Values and settings carry across, and attachments are copied into Softr's storage. |
| Single select, Multiple select | Select | Nothing. Options keep their order and colors. |
| Checkbox, Rating | Checkbox, Rating | Nothing. Icons and colors carry across. |
| Date, Date and time | Date | The time zone carries across, but Airtable's display format (US, European, ISO) doesn't. |
| Long text with rich text | Long text (Markdown) | Formatting comes across as Markdown. Images and @mentions inside the text don't. |
| Created time, Last modified time | Created at, Last updated at | Airtable's original timestamps are kept, and Last modified keeps the fields it was watching. |
| Created by, Last modified by, Collaborator | Created by, Last updated by, User | People come across by name and email. Invite them to your workspace and the fields link to their accounts. |
| Link to another record | Related record | Links are preserved. If you limited which records could be linked, that condition doesn't carry over. |
| Formula | Formula | Softr uses Airtable-compatible syntax, so most formulas work unchanged. Rewrite any that the checklist flags as using an unsupported function. See the [Formula glossary](/softr-databases/formula-glossary). |
| Lookup | [Lookup](/softr-databases/related-record-lookup-and-rollup-fields) | Airtable doesn't expose a lookup's filter, sort, or limit, so a lookup may show more values than it did in Airtable. Compare a few records. |
| Rollup | [Rollup](/softr-databases/related-record-lookup-and-rollup-fields) | Airtable doesn't expose the rollup's calculation, so Softr works it out from your data. Confirm the result and add back any filter. |
| Count | Rollup (count) | A count that only counted some linked records in Airtable will read higher. Add the condition as a rollup filter. |
| AI field | Field with an [AI agent](/softr-databases/ai-agents) | The generated values come across. Check the prompt before turning the agent on. |
| Button, Barcode | Not migrated | Add a URL or formula field if you need the button's link in Softr. |
> **Note**
>
> Softr gives every record a new record ID. If another tool stores Airtable record IDs, update it to use the new ones.
### Review your imported automations
Each Airtable automation comes across as a **draft** [workflow](/workflows/workflows) in Softr. Drafts don't run until you turn them on, so nothing fires while you're still checking.
For each workflow:
1. Open it and fix any step marked **Step incomplete**.
2. Check that the trigger and each step point at the right table and fields in your new database.
3. Test it, then turn it on.
4. Turn off the matching automation in Airtable, so the two don't both run.
A few parts of an Airtable automation need rebuilding rather than reviewing:
- **Scripts.** A **Run script** step becomes a [Run custom code](/workflows/actions/run-custom-code) step, but Airtable's scripting API doesn't exist in Softr, so the script itself needs rewriting.
- **Steps with no Softr equivalent.** Actions for tools Softr doesn't connect to, such as Microsoft Teams, GitHub, or Outlook calendar events, can't be recreated as-is. Rebuild them with another [integration](/workflows/integrations/overview) or a Call API step.
- **Scheduled triggers.** Check the schedule and time zone of any **At scheduled time** trigger.
### Build your app on the new database
Your data now lives in Softr Databases. To put an app on top of it, create or open an app and [connect its blocks](/core-concepts-overview/connect-your-data-source) to the new database. If you already have a classic Softr app on Airtable, use [Migrate an existing Softr app](#migrate-an-existing-softr-app) instead.
## Migrate an existing Softr app
Use this path if you have a classic Softr app that reads its data from Airtable. Classic apps are the apps created before November 2026, and they show a **Classic** tag in **All projects**. Softr moves the app to Softr Databases in three steps:
1. **Import Airtable data to Softr Databases.** Softr imports the tables your app uses, and the tables they link to. Each Airtable base becomes its own Softr database.
2. **Duplicate your app.** Softr makes a copy of your app. The original stays unchanged.
3. **Connect data to app.** Softr updates the copy to use the new Softr databases.
> **Note**
>
> Your original app and your Airtable base stay unchanged. The migration reads from Airtable but doesn't write to it, and you review the copy before you switch your users over. If the import step fails, Softr doesn't make the copy.
> **Info**
>
> New app versions read data through code, which the migration doesn't change, so this path doesn't apply to them.
### Start the migration
1. **Choose the app**
Click **Migrate from Airtable** in the left sidebar, open the **Migrate app** tab, and click **Convert app**. Under **App**, select the app you want to migrate, then click **Convert app**. Only apps that use Airtable as a data source are listed.

_The Migrate app tab and its Convert app button._
You can also start from the app itself:
- When you open the app, Softr can show the **Migrate this app from Airtable to Softr Databases** dialog.
- In the left sidebar of the app editor, click **Migrate**.
- In the **Data** tab of the app editor, open an Airtable base and click **Migrate to Softr Database**.

_The Migrate to Softr Database button in the Data tab._
2. **Start the migration**
In the **Migrate this app from Airtable to Softr Databases** dialog, click **Start migration**.

_Click Start migration to begin._
3. **Wait for the three steps to finish**
Softr shows each step as it runs. The migration can take a few minutes, and Softr lets you know when the copy is ready to review.

_The migration runs in three steps: import the data, duplicate the app, and connect the data to the copy._
### If the app can't be migrated yet
Before the migration starts, Softr checks the app. If a check fails, the dialog shows **This app can't be migrated yet**, and you can't click **Start migration**.

_When a check fails, Start migration stays disabled._
The message doesn't say which check failed. Softr runs the two checks in the order below and stops at the first one that fails, so fix them in this order, then open the dialog again.
| Check | Sign that this check fails |
| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [1. Convert the app to the new app version](#1-convert-the-app-to-the-new-app-version) | The app shows **Can't convert yet** in the app list when you click **Convert app**. Or, the bottom-right corner of the app editor shows **Convert to new app version** or **Finish conversion**. |
| [2. Update old blocks that read Airtable](#2-update-old-blocks-that-read-airtable) | A block that reads Airtable data shows **Block update available** or **This legacy block is no longer supported** at the bottom of its settings panel. |
#### 1. Convert the app to the new app version
Apps made before February 12, 2025 use the legacy app version, and the migration works only for apps on the new app version. If you started the conversion but didn't finish it, the app still counts as not converted.
1. **Start the conversion**
Open the app. Softr may ask **Convert current app to the new version?** straight away. If it doesn't, click **Convert to new app version** in the bottom-right corner of the app editor. Click **How does conversion work?**, then click **Start converting**.
2. **Finish the conversion**
When the conversion is done, click **Finish conversion** in the bottom-right corner of the app editor. The checklist shows the pages that still have blocks the new app version doesn't support, usually header, footer, and user account blocks. Remove them.
3. **Verify**
Click **Verify**. When the checklist shows **All set!**, the conversion is finished.
Softr saves a snapshot of your app before the conversion, which you can go back to from **Settings** > **App History**. Your published app keeps working while you convert. For more details, see [Migrating App Versions](/application-settings/migrating-app-versions).
#### 2. Update old blocks that read Airtable
Older block versions can't show data from Softr Databases, so if an older block reads data from Airtable, the migration can't start. These blocks count:
- Blocks that read data from Airtable, on any page of the app. Hidden blocks count too.
- Sign-up, user profile, and onboarding blocks, if your app users come from an Airtable table.
Blocks on deleted pages don't count.
1. **Check each block**
Open each page. Click each block that reads Airtable data, hidden blocks included, and look at the bottom of the block settings panel.
2. **If you see Block update available**
Click **View details**.
- If the dialog shows **Update now**, click it. Softr updates the block and keeps its settings.
- If the dialog shows **Add new version to app**, click it. Softr adds the new version as a separate block. Set up the new block, then delete the old one.
3. **If you see This legacy block is no longer supported**
Click **Add** and add the new version of the block from the block library. Set it up, then delete the old block.
4. **Delete old blocks you don't use**
You don't have to update an old block that you don't use. You can delete it instead, which is often the fastest fix for hidden blocks.
For more details, see [Block Version Update](/application-settings/block-version-update).
> **Note**
>
> You make these changes in the editor, and your published app doesn't change until you publish. You can also go back to an earlier version from [App History](/application-settings/app-history).
### If the migration didn't finish
If the migration stops after it starts, the app shows **Failed** in the **Migrate app** list. Hover the retry icon in that row to see what went wrong, fix the cause, then click the icon to try again.
The message names each Airtable base by its ID, for example `appAbC123dEf456gH`. To find the base, open it in Airtable: the ID is the part of the URL that starts with `app`. Softr checks only the tables your app uses and the tables they link to.
**Two fields share this name**
The message looks like this: `table 'Projects', field 'Status': Two fields share this name, so references to it cannot be remapped unambiguously`.
Two fields in the same Airtable table have the same name. Upper and lower case don't count as different, so `Status` and `status` are the same name.
Open the table in Airtable and rename one of the two fields, preferably the one your app doesn't use. If you rename a field that your app uses, blocks in your original app that use it can stop working.
**Two tables share this name**
The message ends with `Two tables share this name, so field references cannot be remapped unambiguously`.
Two tables in the same Airtable base have the same name. Upper and lower case don't count as different. Rename one of the two tables in Airtable.
**Softr can't read the Airtable base**
The message looks like this: `This application cannot be migrated - data source appAbC123dEf456gH could not be read - check that the connection still has access to it`. You can also see `No tables were returned for this Airtable base`.
The Airtable connection that the app uses can't read the base. To fix it:
1. In Airtable, make sure the base still exists and that you have access to it.
2. Make sure your Airtable account hasn't used up its API calls for the month.
3. In Softr, open a block that uses the base and go to its **Source** tab. Open the **Base** dropdown and click **Edit bases Softr can access**.
4. In Airtable, give Softr access to the base. We recommend **All current and future bases in all current and future workspaces**.
For more help, see [Airtable](/data-sources/airtable) and [Troubleshooting Airtable Errors](/troubleshooting/troubleshooting-airtable-errors).
**A table or field is over the limit**
A Softr database can have up to 512 tables, and a table can have up to 512 fields. If you see one of these messages, the base or a table is over the limit:
- `Base has 530 tables, the limit for a tablespace is 512`
- `Table has 530 fields, the limit is 512`
For a table with too many fields, delete the fields you don't use in Airtable. For a base with too many tables, contact support.
**A field can't be imported**
You can see one of these messages:
- `Field has no type, which the import cannot translate`
- A message that starts with `Field cannot be translated and would abort the import`
- `No field of this table can be imported, so the table cannot be created`
Contact support and include the full message.
**Something went wrong, please try again**
These messages are usually temporary:
- `Importing data source appAbC123dEf456gH failed, please try again`
- `Could not copy the application's workflows, please try again`
- `Could not start the migration, please try again`
Start the migration again. If you get the same message again, contact support.
### If you don't see the migration option
The app editor shows the **Migrate** item, the **Migrate to Softr Database** button, and the migration dialog only when all of these are true:
- You can edit the app. Workspace guests can't start a migration.
- The app reads data from Airtable.
- The app isn't a copy made by a migration, and it doesn't already have one. To find the copy, go to **Migrate from Airtable** > **Migrate app**.
- The app is a classic Softr app, created before November 2026.
### After the migration
When the migration is done, Softr tells you that your app is migrated. The new app is a copy that uses Softr Databases. Before you publish it:
- **Review your data.** If Softr shows **Review data import**, click it and work through the checklist. See [What transfers, and what to double-check](#what-transfers-and-what-to-double-check).
- **Check your workflows.** The copy gets its own copies of the app's workflows, but their steps still use Airtable. Update them to use Softr Databases.
- **Test as your users.** Preview the app as a user in each [user group](/user-groups-and-permissions/user-groups) and confirm they see exactly what they should, and nothing they shouldn't.
- **Move your domain.** Remove your custom domain from the original app and [add it to the copy](/publishing/add-a-custom-domain-to-your-app).
## Get help
If you can't find the cause of a problem, email . Include the link to your app and the full text of any message you see.
## Related
[**Softr Databases overview**](/softr-databases/softr-databases-overview)
Store your application data natively in Softr.
[**Field types**](/softr-databases/field-types)
Every field type available in Softr Databases.
[**Workflows**](/workflows/workflows)
Automate work across your data and tools.
[**Child's Play Charity case study**](https://www.softr.io/customer-stories/childs-play-charity)
How Base Flows migrated 4,000+ records off Airtable in three weeks.
---
# Migrate a Softr app from Airtable to Softr Databases
Source: https://docs.softr.io/migration-tips/airtable-app-migration
Softr can move an app that uses Airtable to Softr Databases for you. This page explains what the migration does, how to start it, and how to fix each issue that can stop it.
## What the migration does
The migration runs in three steps:
1. Import Airtable data to Softr Databases. Softr imports the tables your app uses, and the tables they link to. Each Airtable base becomes its own Softr database.
2. Duplicate your app. Softr makes a copy of your app.
3. Connect data to app. Softr connects the copy to the new Softr databases.
> **Note**
>
> Your original app and your Airtable base stay unchanged. The migration reads from Airtable but does not write to it. You review the copy before you switch your users over.
If the import step fails, Softr does not make the copy.
## Start a migration
You can start a migration in these places:
- When you open the app, Softr can show the **Migrate this app from Airtable to Softr Databases** dialog.
- In the left sidebar of the app editor, click **Migrate**.
- In the Data tab of the app editor, click **Migrate to Softr Database**.
- On your dashboard, go to **Migrate from Airtable** > **Migrate app** and click **Convert app**. Then select the app.
In the dialog, click **Start migration**. The migration can take a few minutes.
## If the app can't be migrated yet
Before the migration starts, Softr checks the app. If a check fails, the dialog shows **This app can't be migrated yet**, and you can't click **Start migration**.
The message does not say which check failed. Softr runs the two checks in the order below and stops at the first one that fails. Fix them in this order, then open the dialog again.
| Check | Sign that this check fails |
| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [1. Convert the app to the new app version](#1-convert-the-app-to-the-new-app-version) | The app has a **Legacy** tag on your dashboard. Or, the bottom-right corner of the app editor shows **Convert to new app version** or **Finish conversion**. |
| [2. Update old blocks that read Airtable](#2-update-old-blocks-that-read-airtable) | A block that reads Airtable data shows **Block update available** or **This legacy block is no longer supported** at the bottom of its settings panel. |
> **Tip**
>
> On the **Migrate from Airtable** > **Migrate app** page of your dashboard, the app list shows **Can't convert yet** next to apps that fail check 1.
### 1. Convert the app to the new app version
Apps made before February 12, 2025 use the legacy app version. The migration works only for apps on the new app version. If you started the conversion but did not finish it, the app still counts as not converted.
1. **Start the conversion**
Open the app. In the bottom-right corner of the app editor, click **Convert to new app version**. Click **How does conversion work?**, then click **Start converting**.
2. **Finish the conversion**
When the conversion is done, click **Finish conversion** in the bottom-right corner of the app editor. The checklist shows the pages that still have blocks the new app version does not support. These are usually header, footer, and user account blocks. Remove them.
3. **Verify**
Click **Verify**. When the checklist shows **All set!**, the conversion is finished.
Softr saves a snapshot of your app before the conversion. You can go back to it from **Settings** > **App History**. Your published app keeps working while you convert.
For more details, see [Migrating App Versions](/application-settings/migrating-app-versions).
### 2. Update old blocks that read Airtable
Older block versions can't show data from Softr Databases. If a block of an older version reads data from Airtable, the migration can't start. Update these blocks first.
These blocks count:
- Blocks that read data from Airtable, on any page of the app. Hidden blocks count too.
- Sign-up, user profile, and onboarding blocks, if your app users come from an Airtable table.
Blocks on deleted pages do not count.
To find and update the old blocks:
1. **Check each block**
Open each page. Click each block that reads Airtable data, hidden blocks included. Look at the bottom of the block settings panel.
2. **If you see Block update available**
Click **View details**.
- If the dialog shows **Update now**, click it. Softr updates the block and keeps its settings.
- If the dialog shows **Add new version to app**, click it. Softr adds the new version as a separate block. Set up the new block, then delete the old block.
3. **If you see This legacy block is no longer supported**
Click **Add** and add the new version of the block from the block library. Set it up, then delete the old block.
4. **Delete old blocks you don't use**
You don't have to update an old block that you don't use. You can delete it instead. This is often the fastest fix for hidden blocks.
For more details, see [Block Version Update](/application-settings/block-version-update).
> **Note**
>
> You make these changes in the editor. Your published app does not change until you publish. You can also go back to an earlier version from [App History](/application-settings/app-history).
## If the migration didn't finish
If the migration stops after it starts, the dialog closes and an error message opens with the title **The migration didn't finish**. The message tells you what went wrong.
The message names each Airtable base by its ID, for example `appAbC123dEf456gH`. To find the base, open it in Airtable: the ID is the part of the URL that starts with `app`. The message shows up to five issues. Fix all of them, then start the migration again.
Softr checks only the tables your app uses and the tables they link to.
### Two fields share this name
The message looks like this: `table 'Projects', field 'Status': Two fields share this name, so references to it cannot be remapped unambiguously`.
Two fields in the same Airtable table have the same name. Upper and lower case do not count as different, so `Status` and `status` are the same name.
To fix it, open the table in Airtable and rename one of the two fields. Rename the field your app does not use. If you rename a field that your app uses, blocks in your original app that use it can stop working.
### Two tables share this name
The message ends with `Two tables share this name, so field references cannot be remapped unambiguously`.
Two tables in the same Airtable base have the same name. Upper and lower case do not count as different. Rename one of the two tables in Airtable.
### Softr can't read the Airtable base
The message looks like this: `data source appAbC123dEf456gH could not be read - check that the connection still has access to it`. You can also see `No tables were returned for this Airtable base`.
The Airtable connection that the app uses can't read the base. To fix it:
1. In Airtable, make sure the base still exists and that you have access to it.
2. In Softr, open a block that uses the base and go to its **Source** tab. Open the **Base** dropdown and click **Edit bases Softr can access**.
3. In Airtable, give Softr access to the base. We recommend **All current and future bases in all current and future workspaces**.
For more help, see [Airtable](/data-sources/airtable) and [Troubleshooting Airtable Errors](/troubleshooting/troubleshooting-airtable-errors).
### A table or field is over the limit
A Softr database can have up to 512 tables. A table can have up to 512 fields. If you see one of these messages, the base or a table is over the limit:
- `Base has 530 tables, the limit for a tablespace is 512`
- `Table has 530 fields, the limit is 512`
For a table with too many fields, delete the fields you don't use in Airtable. For a base with too many tables, contact support.
### A field can't be imported
You can see one of these messages:
- `Field has no type, which the import cannot translate`
- A message that starts with `Field cannot be translated and would abort the import`
- `No field of this table can be imported, so the table cannot be created`
Contact support and include the full message.
### Something went wrong, please try again
These messages are usually temporary:
- `Importing data source appAbC123dEf456gH failed, please try again`
- `Could not copy the application's workflows, please try again`
- `Could not start the migration, please try again`
Start the migration again. If you get the same message again, contact support.
## If you don't see the migration option
The app editor shows the **Migrate** item, the **Migrate to Softr Database** button, and the migration dialog only when all of these are true:
- You can edit the app. Workspace guests can't start a migration.
- The app reads data from Airtable.
- The app is not a copy made by a migration, and it does not already have one. To find the copy, go to **Migrate from Airtable** > **Migrate app** on your dashboard.
- The app is not a vibe coding app. Vibe coding apps read data through code, and the migration does not change code.
## After the migration
When the migration is done, the dialog tells you that your app is migrated. The new app is a copy that uses Softr Databases. Before you publish it:
- Review your data. Some database settings may not migrate fully because of Airtable limitations. If the dialog shows **Review data import**, click it and update the settings as needed. See [What transfers, and what to double-check](/migration-tips/migrating-from-airtable-to-softr-databases#what-transfers-and-what-to-double-check).
- Check your workflows. The copy gets its own copies of the app's workflows, but their steps still use Airtable. Update them to use Softr Databases.
- Move your domain. Remove your custom domain from the original app and add it to the copy.
## Get help
If you can't find the cause, email . Include the link to your app and the full text of any message you see.
---
# List Block
Source: https://docs.softr.io/building-blocks/list-block
**List blocks** display collections of items, like contacts, tasks, or projects, in a list format. They include interactive options that let users filter, sort, or create and update items.
Each item in a List block can show details such as titles, descriptions, images, tags, and other fields.

## **Use case examples**
- **Product Inventory**: Display items in stock with details like product name, SKU, quantity, and location. Users can filter by category or availability to track stock levels.
- **Employee Directory**: Create a searchable list of employees with details like name, position, department, and contact information.
- **Real Estate Listings**: Showcase properties with images, location, price, and property details. Users can filter by property type, location, or price range.
- **Client List**: Organize client information, including industry, location, and project status, to help teams track and access client data.
# Configure a List block
> **Tip**
>
> **Build with AI:** Instead of configuring manually, you can add a List block instantly with the **AI Co-Builder**. Just click the AI icon in the editor and type: _"Add a List block showing my team members, including their name, picture, and department."_
## Source
The **Source** panel connects the list block to your data source. Here, you can:
- Connect the list block to your [data source](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/connect-your-data-source/41p6U2eZs6NZ5qZp7iKvnn).
- Set up [conditional filters](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/conditional-filters/mDnn7jnpPiYmJcT99jpt7m) to display only the data that meets specific criteria.
- **Define sorting rules** and set the number of items to display per page.
- **Customize the empty state message** that appears when no data matches the requirements.
Once you connect to your source data, you can configure Content, Actions, and block Visibility settings.
> **Info**
>
> Some configuration options depend on the [data source](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/connect-your-data-source/41p6U2eZs6NZ5qZp7iKvnn). For more details, check the documentation for your specific data source.

## **Content**
In the **Content** tab, customize the List block layout and the data fields in your list block, adjust their display, and add features like search and filters to help users find information quickly.
### **Sections**
The List block includes two display areas:
- The **Main Section** is the primary display area for each list item. It remains visible even when an item isn’t selected.
- The **Secondary Section** is an optional area in the list block for showing additional or supporting information that doesn’t need to be visible at first glance.

### **Item fields**
**Item Fields** lets you connect fields from your **data source** to each list item, making it easy to display the information you need. You can control what information appears by adding, removing, or rearranging fields such as task names, assignees, or descriptions.
For each field in the **Item Fields** section of the secondary section, you can customize the following options:
- **Type:** Defines the display field type that controls how content appears in the block (e.g., text, checkbox, or image).
- **Content:** Chooses the specific data field from connected data sources to display.
- **Label (Optional):** Adds context to the field. If left blank, the label will not be visible to users.

> **Info**
>
> **Note:** Some display field types are compatible only with specific data formats. For example, if a field is set to display images, you cannot map it to text data. Ensure the field type matches your data source field format to avoid display issues.
**Supported field types**
| | |
| ----------------- | --------------------------------------------------------------------------------------------------------- |
| **Display Field** | **Description** |
| **Text** | Displays plain text. Ideal for names, titles, or short descriptions. |
| **Rich Text** | Supports long text, markdown, or HTML formatting. Allows for more detailed descriptions or notes. |
| **Headings** | Various heading sizes |
| **Email** | Displays email addresses as clickable mailto links, allowing users to start an email directly. |
| **URL** | Displays website links as clickable URLs, allowing users to navigate to external pages. |
| **Tag** | Allows you to display one or more tags, helpful for organizing items by category or status. |
| **File** | Provides a link for users to download attachments, such as PDFs or other documents. |
| **Video** | Embed video content from a supported source, allowing users to watch content directly in the block. |
| **Audio** | Embed audio files, letting users listen to content directly within the block. |
| **Image** | Displays a single image, useful for things like profile pictures or product images. |
| **Image gallery** | Displays multiple images in a gallery format, useful for showcasing a collection of visuals. |
| **Embed** | Allows you to embed content from other services, such as YouTube videos, Calendly, or social media posts. |
| **Rating** | Displays a rating system, typically with stars, to visually represent ratings or scores. |
| **Checkbox** | Shows a checkbox, useful for indicating completed items or allowing users to mark items as done. |
### **Search bar**
The **Search Bar** allows users to search through items in your block, making it easier to find specific entries quickly.
You can configure which parameters you want the search to be performed by adding fields to Search by input. For instance, if you’re displaying a list of employees, you might select “Name,” “Department,” and “Job title” as searchable fields.

> **Info**
>
> If no fields are selected, the search bar will display all items regardless of the search term. To ensure meaningful search results, always select at least one field.
### **Filters**
Filters allow your app users to narrow down list items based on specific fields, making it easier to find what they need without scrolling through all the items. You can set up one or more filters in the block to enhance user search functionality.
Choose between a **Dropdown** menu (collapsible for large option sets) or **Tags** (clickable labels for frequently used categories). Depending on your layout needs, decide where filters will appear—at the t**op** or **Left** of the block.

For each filter, you can configure:
- **Label**: Add a descriptive label to guide users, such as **"Filter by Status"** or **"Filter by Category**.”
- **Field**: Select the data field users can filter by, such as **Status**, **Category**, or **Language**.
- **Options**: Define the values users can select in the filter.
- **When Sync with Data Source is Enabled,** the filter options automatically pull all available values from your data source. You can then select which of these synced values to display in the filter, making it easy to keep options updated while retaining customization. \*This feature is only available for specific field types, such as **single-select**, **multi-select**, and **linked record** fields.
- **When Sync is Disabled**: You must manually define and update the filter options. This allows full control over which values appear but requires manual changes whenever your data is updated.
- **Sorting Options**: You can arrange filter options alphabetically (**A-Z** or **Z-A**) or in a custom order based on relevance.
- **Multi-select (Optional):** This option allows users to select multiple filter options at a time. It is useful when filtering by multiple categories, statuses, or other fields simultaneously.

**Filtering the Filter Options**
You can also filter the filter options to display different options based on user attributes, selected records, etc. Just click on the branching icon next to the Options subtitle:

Then toggle it on and setup the conditions you want to apply to filter to the filter.

### **Embed Block**
You can embed any Softr block in another application. Learn how in our [Page and Block Embed](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/page-and-block-embed/kaMvDCneGdx43AxHnmf7bm) guide.
## Actions
[Actions](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/actions-adding-and-editing-data-/41p6U2eZs87asLz6dV5AMy) let you define what happens when users interact with a block, such as navigating to a new page, editing records, or triggering workflows. This ensures your app not only displays data but also offers dynamic user engagement.

**Topbar buttons**
- [Add record](/actions/ntEfT9zSJk6aY54G6W5KGU/add-record/3LrUMpQY4BKfDDQj6eb8h8): Create new entries in your data.
- [Open page](/actions/ntEfT9zSJk6aY54G6W5KGU/item-on-click-actions/f1ns7phZfNNvgwXA6tTN3M): Navigate to another page within your app.
- **Open URL**: Redirect users to an external link.
- **Scroll to**: Move the view to a specific section within the block.
- [Export](/actions/ntEfT9zSJk6aY54G6W5KGU/export/mnrvzncWeoSfwWJscZCAxC):Export visible records.
**Item buttons**
- [Edit record](/actions/ntEfT9zSJk6aY54G6W5KGU/edit-record/irSJXPF1gCMXNmfsQFscvx): Modify the details of a specific record.
- [One-Click Update](/actions/ntEfT9zSJk6aY54G6W5KGU/one-click-update/8BaX5i6KLZhZCrSZERGnej): Apply predefined updates to a record with a single click.
- [Open details page](/actions/ntEfT9zSJk6aY54G6W5KGU/item-on-click-actions/f1ns7phZfNNvgwXA6tTN3M): Open the details page of the selected record.
- [Delete Record](/actions/ntEfT9zSJk6aY54G6W5KGU/delete-record/peV9LGdJbM9sKHKynqopkH): Remove a record from your data.
- **Open URL**: Redirect users to an external link.
- [Download file](/actions/ntEfT9zSJk6aY54G6W5KGU/download-file/8Sr2y4CREVcW2GEEDYUhfJ): Provide users with a direct option to download associated files.
- [Call API](/actions/ntEfT9zSJk6aY54G6W5KGU/call-api/i9f1s3w9wib3oRmS4HZ7MX): This action triggers a custom API call for advanced integrations (_available for Professional, Business, and Enterprise plans)._
**On Click Actions:**
- **Do nothing:** Nothing happens when the user clicks on the item.
- **Open URL**: Redirect users to an external link.
- **Scroll to**: Move the view to a specific section within the block.
- **Open details page**: Open the details page of the selected record.
## Visibility
Control who can see a block by setting up [visibility](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/block-visibility/3spA2dfQNrcGcPNmnDXHB3) rules. This helps tailor the user experience by showing relevant content to the right audience, improving personalization and security.

## Style
Customize the look and feel of your blocks with s[tyling](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/style-your-app/41p6U2eZs8AZmBW8mHykXA) options. Adjust fonts, colors, spacing, and more to align with your app’s branding and create a polished, professional design.

## Relevant Guides
- [How to set up a record detail page?](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/item-details-block-/4bE8XaFbJp45wkAwuWiz8f)
- [How to filter list records by Page URL parameter?](/how-to-guides/ioi5BbuQ2RDM7aHPrpXnjG/how-to-filter-list-by-page-url-parameters/42JZoeYwMstwaL9aoBdRjz)
---
# Grid Block
Source: https://docs.softr.io/building-blocks/grid-block
**Grid Blocks** display collections of items, such as products, tasks, or contacts, in a visually appealing grid format. Each item appears as a card with space for images, titles, descriptions, and other relevant details. The layout is ideal for presenting content that benefits from strong visual elements, like product images or profile pictures.
Cards within a Grid Block are interactive, enabling users to filter, sort, and update items seamlessly.

## **Use case examples**
- **Product Inventory:** Display products in a grid with images, names, SKUs, and stock details. Users can filter by category, availability, or location to easily track inventory.
- **Employee Directory:** Present team members in a searchable grid with photos, names, roles, departments, and contact information for quick reference.
- **Real Estate Listings:** Showcase properties as visually engaging cards with property images, locations, prices, and key features. Allow users to filter by price range, property type, or location.
# Configure a Grid block
> **Tip**
>
> **Build with AI:** Instead of configuring manually, you can add a Grid block instantly with the **AI Co-Builder**. Just click the AI icon in the editor and type: _"Create a grid of products showing their image, name, and price."_
## Source
The **Source** panel connects the list block to your data source. Here, you can:
- Connect the list block to your [data source](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/connect-your-data-source/41p6U2eZs6NZ5qZp7iKvnn).
- Set up [conditional filters](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/conditional-filters/mDnn7jnpPiYmJcT99jpt7m) to display only the data that meets specific criteria.
- **Define sorting rules** and set the number of items to display per page.
- **Customize the empty state message** that appears when no data matches the requirements.
Once you connect to your source data, you can configure Content, Actions, and block Visibility settings.
> **Info**
>
> Some configuration options depend on the [data source](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/connect-your-data-source/41p6U2eZs6NZ5qZp7iKvnn). For more details, check the documentation for your specific data source.

## **Content**
In the **Content** tab, customize the List block layout and the data fields in your list block, adjust their display, and add features like search and filters to help users find information quickly.
### **Item fields**
**Item Fields** lets you connect fields from your **data source** to each list item, making it easy to display the information you need. You can control what information appears by adding, removing, or rearranging fields such as task names, assignees, or descriptions.
For each field in the **Item Fields** section of the secondary section, you can customize the following options:
- **Type:** Defines the display field type that controls how content appears in the block (e.g., text, checkbox, or image).
- **Content:** Chooses the specific data field from connected data sources to display.
- **Label (Optional):** Adds context to the field. If left blank, the label will not be visible to users.

> **Info**
>
> **Note:** Some display field types are compatible only with specific data formats. For example, if a field is set to display images, you cannot map it to text data. Ensure the field type matches your data source field format to avoid display issues.
**Supported field types**
| | |
| ------------------- | --------------------------------------------------------------------------------------------------------- |
| **Display Field** | **Description** |
| **Cover media** | Display a featured image as a prominent top section element. |
| **Cover media tag** | Allows you to display one or more tags on top of cover media. |
| **Text** | Displays plain text. Ideal for names, titles, or short descriptions. |
| **Rich Text** | Supports long text, markdown, or HTML formatting. Allows for more detailed descriptions or notes. |
| **Headings** | Various heading sizes |
| **Email** | Displays email addresses as clickable mailto links, allowing users to start an email directly. |
| **URL** | Displays website links as clickable URLs, allowing users to navigate to external pages. |
| **Tag** | Allows you to display one or more tags, helpful for organizing items by category or status. |
| **File** | Provides a link for users to download attachments, such as PDFs or other documents. |
| **Video** | Embed video content from a supported source, allowing users to watch content directly in the block. |
| **Audio** | Embed audio files, letting users listen to content directly within the block. |
| **Image** | Displays a single image, useful for things like profile pictures or product images. |
| **Image gallery** | Displays multiple images in a gallery format, useful for showcasing a collection of visuals. |
| **Embed** | Allows you to embed content from other services, such as YouTube videos, Calendly, or social media posts. |
| **Rating** | Displays a rating system, typically with stars, to visually represent ratings or scores. |
| **Checkbox** | Shows a checkbox, useful for indicating completed items or allowing users to mark items as done. |
### **Search bar**
The **Search Bar** allows users to search through items in your block, making it easier to find specific entries quickly.
You can configure which parameters you want the search to be performed by adding fields to Search by input. For instance, if you’re displaying a list of employees, you might select “Name,” “Department,” and “Job title” as searchable fields.

> **Info**
>
> If no fields are selected, the search bar will display all items regardless of the search term. To ensure meaningful search results, always select at least one field.
### **Filters**
Filters allow your app users to narrow down list items based on specific fields, making it easier to find what they need without scrolling through all the items. You can set up one or more filters in the block to enhance user search functionality.
Choose between a **Dropdown** menu (collapsible for large option sets) or **Tags** (clickable labels for frequently used categories). Depending on your layout needs, decide where filters will appear—at the t**op** or **Left** of the block.

For each filter, you can configure:
- **Label**: Add a descriptive label to guide users, such as **"Filter by Status"** or **"Filter by Category**.”
- **Field**: Select the data field users can filter by, such as **Status**, **Category**, or **Language**.
- **Options**: Define the values users can select in the filter.
- **When Sync with Data Source is Enabled,** the filter options automatically pull all available values from your data source. You can then select which of these synced values to display in the filter, making it easy to keep options updated while retaining customization. \*This feature is only available for specific field types, such as **single-select**, **multi-select**, and **linked record** fields.
- **When Sync is Disabled**: You must manually define and update the filter options. This allows full control over which values appear but requires manual changes whenever your data is updated.
- **Sorting Options**: You can arrange filter options alphabetically (**A-Z** or **Z-A**) or in a custom order based on relevance.
- **Multi-select (Optional):** This option allows users to select multiple filter options at a time. It is useful when filtering by multiple categories, statuses, or other fields simultaneously.

**Filtering the Filter Options**
You can also filter the filter options to display different options based on user attributes, selected records, etc. Just click on the branching icon next to the Options subtitle:

Then toggle it on and setup the conditions you want to apply to filter to the filter.

### **Embed Block**
You can embed any Softr block in another application. Learn how in our [Page and Block Embed](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/page-and-block-embed/kaMvDCneGdx43AxHnmf7bm) guide.
## Relevant Guides
- [How to set up a record detail page?](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/item-details-block-/4bE8XaFbJp45wkAwuWiz8f)
- [How to filter list records by Page URL parameter?](/how-to-guides/ioi5BbuQ2RDM7aHPrpXnjG/how-to-filter-list-by-page-url-parameters/42JZoeYwMstwaL9aoBdRjz)
---
# Layout: List with small cards
Source: https://docs.softr.io/building-blocks/layout-list-with-small-cards

_List with small cards_
This layout allows organizing your data into a grid with smaller cells. It's perfect when you don't need to show much info for each record and need to fit a bigger number of items into the given space. Below you can see an example of using this layout to display brief people profiles with image, email, and name.

_Using the layout to create a list of profiles_
---
# Layout: List with timeline
Source: https://docs.softr.io/building-blocks/layout-list-with-timeline
> **Note**
>
> List with timeline block is available for users on the [Business plan and above](https://www.softr.io/pricing).

_List with timeline_
With this layout you can organize your List items in a vertical timeline. Below is an example of a timeline list that presents projects sorted by their completion date.

_Projects comletion timeline_
---
# Layout: Inbox
Source: https://docs.softr.io/building-blocks/layout-inbox
> **Note**
>
> Inbox block is available for users on the [Professional plan and above](https://www.softr.io/pricing).
The Inbox layout works similar to an email inbox where you select an item from the sidebar on the left side of the screen and its details are displayed inside the window next to it dynamically.

The Inbox layout is configured similar to the other [List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU) layouts, but the field mapping part has some nuances. So, let's take a closer look at that.
## **Mapping the fields**
The layout has a set of fixed fields (4 of them under **List Item**) that represent the values in the left sidebar.

_List item fields_
Below, we've mapped those fields to an [Airtable](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX) base, and you can see how they're displayed inside the sidebar. Note that one of the fields is hidden, so you can show/hide them based on your needs.

_Mapping the sidebar fields_
Next, you have the **List Detail Fields** (you can add or remove as many fields as you wish) that represent the details section of the list item. Below, you can see that we've used two fields, and now their values are displayed in the details window for each list item. **The fields we've used are different from those that we used for the sidebar part, but you can use the same fields again.**

_Mapping List Item Fields_
---
# Item Details Block
Source: https://docs.softr.io/building-blocks/item-details-block-
## Video
## Overview
The Item details block displays detailed information for a specific record, like a project or client. Users typically access it by clicking on an item in a dynamic block, such as a List or Grid. This action triggers the display of relevant details pages for that specific record, eliminating the need to create separate pages for every individual item in your database.
The item detail block is for showing detailed information about one record (or one row) in your database. Therefore, we need a way to define which record will be shown in it. We have three ways to do this:
1. **Easiest and Best Method**: You can set a list of many records on a previous page so that when a user clicks on an item in the list, they are taken to an item details to see more info about the record they selected. This is the method we are demonstrating in this guide.
2. **For specific use cases**: If no list or records exists for them to click on first (for instance showing a logged-in users company details), you can setup filtering to narrow down the record shown by the items details block to a specific record. Be careful though - if the filter is not specific enough, Softr will try to find a good example record from your database to display.
3. **For advanced use cases**: The third option is to specify which record to display using a URL to your Softr app for a specific record. You can get these by copying from a live version of the app _**or**_ you can also create them in your database by constructing URLs using the `?recordId=` parameter on the end of the page slug like `https://yourapp.softr.app/item-details?recordId=XXXXX`

> **Tip**
>
> The Item Details block works best when placed at the very top of the page, especially if there are other blocks on the page that are using its details for filtering, visibility, etc.
## **Use case examples**
- **Product Details**: Showcase detailed product information when a user selects an item from a product list. For example, display product descriptions, images, prices, and ratings.
- **Task Management**: Provide task-specific details, including deadlines, assigned users, and notes. For example, create a task detail page for team collaboration.
- **Client Details**: Display client information when a user selects a client from a list. For example, show client contact information, recent interactions, project history, or account status.
# **Configure an Item details block**
> **Tip**
>
> **Build with AI:** Instead of configuring manually, you can add an Item details block instantly with the **AI Co-Builder**. Just click the AI icon in the editor on your details page and type: _"Create a details page for a project, showing the hero image, description, and related tasks."_
To configure the Item details block to show a specific record detail when the user clicks on an item on a dynamic block, you will need to have a [dynamic block](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/visualize-data-with-building-blocks/41p6U2eZs7zgY8zWmFV4eH#dynamic-blocks), e.g., [List](/bd9fd66f6e394867bfb70d838c4f8def?pvs=25), connected to the [data source](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/connect-your-data-source/41p6U2eZs6NZ5qZp7iKvnn). Once you have it ready, follow these steps:
1. Add an Item details block to a new page.
2. Connect the Item details block to the same data source (e.g., Airtable Base and Table) as the List block.
3. Go to the **List** block settings and navigate to the **Actions** tab.
4. Set the [Item On Click](/actions/ntEfT9zSJk6aY54G6W5KGU/item-on-click-actions/f1ns7phZfNNvgwXA6tTN3M) action to **Open page** and select the page containing the Item details block you created.
**Result**: When users click on a list item, they’re directed to a page showing detailed information for that item.
Once you connect to your source data, you can configure [Conditional Filters](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/conditional-filters/mDnn7jnpPiYmJcT99jpt7m), Content, Actions, and block Visibility settings.
> **Info**
>
> Some configuration options depend on the data source. For more details, check the documentation for your specific data source.
## **Content**
In the **Content** tab, customize the Item detail block layout and the data fields and adjust their display.
### Sections
The Item Details block includes two types of sections for organizing fields:
- **Default Top Section**: Ideal for key information like titles, images, or categories (e.g., a product name and featured image).
- **Custom Sections**: Add multiple sections for additional details (e.g., project assets or milestones).
This structure keeps detail pages organized and easy to navigate.

### **Item fields**
**Item Fields** lets you connect fields from your **data source** to each list item, making it easy to display the information you need. You can control what information appears by adding, removing, or rearranging fields such as task names, assignees, or descriptions.
For each field in the **Item Fields** section of the secondary section, you can customize the following options:
- **Type:** Defines the display field type that controls how content appears in the block (e.g., text, checkbox, or image).
- **Content:** Chooses the specific data field from connected data sources to display.
- **Label (Optional):** Adds context to the field. If left blank, the label will not be visible to users.

> **Info**
>
> **Note:** Some display field types are compatible only with specific data formats. For example, if a field is set to display images, you cannot map it to text data. Ensure the field type matches your data source field format to avoid display issues.
**Supported Field Types**
| | |
| ----------------- | --------------------------------------------------------------------------------------------------------- |
| **Display Field** | **Description** |
| **Cover Media** | Display a featured image as a prominent top section element. |
| **Text** | Displays plain text. Ideal for names, titles, or short descriptions. |
| **Rich Text** | Supports long text, markdown, or HTML formatting. Allows for more detailed descriptions or notes. |
| **Headings** | Various heading sizes |
| **Email** | Displays email addresses as clickable mailto links, allowing users to start an email directly. |
| **URL** | Displays website links as clickable URLs, allowing users to navigate to external pages. |
| **Tag** | Allows you to display one or more tags, helpful for organizing items by category or status. |
| **File** | Provides a link for users to download attachments, such as PDFs or other documents. |
| **Video** | Embed video content from a supported source, allowing users to watch content directly in the block. |
| **Audio** | Embed audio files, letting users listen to content directly within the block. |
| **Image** | Displays a single image, useful for things like profile pictures or product images. |
| **Image gallery** | Displays multiple images in a gallery format, useful for showcasing a collection of visuals. |
| **Embed** | Allows you to embed content from other services, such as YouTube videos, Calendly, or social media posts. |
| **Rating** | Displays a rating system, typically with stars, to visually represent ratings or scores. |
| **Checkbox** | Shows a checkbox, useful for indicating completed items or allowing users to mark items as done. |
**Filtering the Filter Options**
You can also filter the filter options to display different options based on user attributes, selected records, etc. Just click on the branching icon next to the Options subtitle:

Then toggle it on and setup the conditions you want to apply to filter to the filter.

### **Embed Block**
You can embed any Softr block in another application. Learn how in our [Page and Block Embed](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/page-and-block-embed/kaMvDCneGdx43AxHnmf7bm) guide.
## Actions
[Actions](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/actions-adding-and-editing-data-/41p6U2eZs87asLz6dV5AMy) let you define what happens when users interact with a block, such as navigating to a new page, editing records, or triggering workflows. This ensures your app not only displays data but also offers dynamic user engagement.

**Item buttons**
- [Edit record](/actions/ntEfT9zSJk6aY54G6W5KGU/edit-record/irSJXPF1gCMXNmfsQFscvx): Modify the details of a specific record.
- [One-Click Update](/actions/ntEfT9zSJk6aY54G6W5KGU/one-click-update/8BaX5i6KLZhZCrSZERGnej): Apply predefined updates to a record with a single click.
- [Open details page](/actions/ntEfT9zSJk6aY54G6W5KGU/item-on-click-actions/f1ns7phZfNNvgwXA6tTN3M): Open the details page of the selected record.
- [Delete Record](/actions/ntEfT9zSJk6aY54G6W5KGU/delete-record/peV9LGdJbM9sKHKynqopkH): Remove a record from your data.
- **Open URL**: Redirect users to an external link.
- [Download file](/actions/ntEfT9zSJk6aY54G6W5KGU/download-file/8Sr2y4CREVcW2GEEDYUhfJ): Provide users with a direct option to download associated files.
- [**Export**](/actions/ntEfT9zSJk6aY54G6W5KGU/export/mnrvzncWeoSfwWJscZCAxC): Export visible record or page.
- **Scroll to**: Move the view to a specific section within the block.
- [Call API](/actions/ntEfT9zSJk6aY54G6W5KGU/call-api/i9f1s3w9wib3oRmS4HZ7MX): This action triggers a custom API call for advanced integrations _(available for Professional, Business, and Enterprise plans)._
## **Showing detailed information based on logged-in user data**
In addition to showing Item details connected to a list block, you can also set up an Item details block to show details based on logged-in user data without needing an additional list block. E.g., show company profile details for the logged-in client.
Follow these steps to set it up:
1. Create a new page and add an Item details block.
2. Connect the Item details block to the same **data source** (e.g., Airtable Base and Table) where you store the user data.
3. Apply [Conditional Filters](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/conditional-filters/mDnn7jnpPiYmJcT99jpt7m) to display data based on user attributes dynamically.
**Example:** Filter records where the logged-in user’s company matches the name field in the company database. Result: Users who open the page with this detail block will see only their company information.

## Relevant Guides
- [How to show additional related records on the details page?](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/linked-list/bWjTdKhbftofSEKRSxMFz9)
- [How to set up SEO for detail pages?](/publishing/9qTmU2Lj8Gnpr1Ue6dEAkX/item-details-seo/6QnbCZTZjYbctWHbqcPaSJ)
- [How to enable users to comment on the details page?](/697c2ac57a3c40a8b5c14cc7bcf8947c?pvs=25)
- [Use Case: Creating a User Profile with List Details](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/use-case-creating-a-user-profile-with-item-details/e4isniZBZBRV1zxEEU8dct)
- [Use Case: Embedding Calendly in List Details](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/use-case-embedding-calendly-in-list-details/pUraLKqtjajCRizCqhAJLR)
---
# Linked List
Source: https://docs.softr.io/building-blocks/linked-list
## Video
## Overview
Before reading this article, we highly recommend watching the above video and checking out our Item Details help article. It will really help you understand how this should all work.
One of the most powerful parts of Softr is being able to display not only individual details about a specific record, but also any other records that may be related to that specific record. For example, you may want to display a list of files, team members, or invoices related to a specific project. This is where Linked Lists come in.
Below we’ll look at a quick example using Projects and Tasks related to projects, but you can do this with any data type you can imagine.
> **Tip**
>
> Linked Lists work best when they are placed below Item Details blocks that they are using for filtering, visibility, etc. Placing them above Item Details blocks they are using may cause issues in rendering them on the page.
# **Example Setup**
1. Create a "Projects" table\

_Projects table_
2. Create "Tasks" table to hold task-related data, including a field referencing the associated Project. It can be a [Lookup field](https://support.airtable.com/hc/en-us/articles/360042312194-Lookup-field-overview) that looks up the **Name** field from the **Projects** table, but it can also be a regular field that contains the names of the projects, as in the example below.\

_Table with tasks_
# **Implementation**
1. On e.g. “Projects” page, add a **List** block linked to the Project [Airtable](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX) table as shown below.

_List block with projects_
1. On e.g. “Project details” page, add a List Details block, again linked to the Projects Airtable table.
2. On this detail page, add also a List block, linked to the Tasks Airtable table

_Task list added to the Project details page_
# **Configuration**
As soon as you add the **Tasks** list to the project's details page, you'll see that the **Projects** table's fields will start appearing inside **Conditional Filters** of the **Tasks** list block.

_Projects table inside Task List's conditional filters_
Using this, we can now set a condition to filter the **Tasks** list to show only the tasks that are associated with the project that's currently opened in the page. The condition will be set as shown below.

_Setting the filtering condition_
So, only the tasks for which the value in the **Project** column corresponds to the current project's **Name** will be shown.
# Result
Let's check how that works for the **Ad Campaign** project that includes two tasks (assigned to and ).

_Testing the result_
That's it. Now, each project details page will also show all the tasks associated to it.
---
# Comments block
Source: https://docs.softr.io/building-blocks/comments-block
The Comments block lets users add and view comments linked to a specific item in your app — like a project, task, or client. It’s perfect for sharing updates, asking questions, or keeping track of important details in one place.
### Key things to know
- Comments can be enabled from any [Item detail block](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/item-details-block-/4bE8XaFbJp45wkAwuWiz8f)or any list type block ([List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU), [Grid](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/grid-block/42JZoeYwMsogZcveqh74QH), [Table](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/table-block-/j7rGwu7J7zuU69h3bZ7HFe))
- **Comments are always linked to a record** — they can’t exist on their own.
- You **don’t need to set up an extra table** to store them. Comments are saved directly inside your Softr app.
- Each record has **one comment thread**, even if you show it in multiple places.
- You can show comments as:
- A **block** on a details page
- A **side panel** (new!) that opens when clicking a button on a list
### Examples
Here’s how you can use comments in your app:
- **Projects** – Let your team discuss project updates or next steps.
- **Support tickets** – Add internal notes or track follow-ups.
- **Clients** – Keep a record of conversations or important context.
### How to set up Comments block for Item detail block
1. Enable the **Comments block** in the **Action** tab of the [**Item detail block**](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/item-details-block-/4bE8XaFbJp45wkAwuWiz8f)\

2. Choose if you want to show comments as a block or side panel.\

3. Configure Features, Permissions and Style in Comments Settings\

### How to set up Comments for a List block
1. Add a new **Item button** in the **Actions tab** → **Open Comments.**\

2. Note: In this case, the Comments tab can only be visualized in a **Side panel.**\

3. Configure Features, Permissions, and Style in **Comments Settings**
### Comments settings and customization
Go to **Settings → Comments** to control how comments work across your app. From there, you can:
- Add features like **Rich text formatting** and **file upload** option.
- Change the **sorting order**, visual **style**, and **message text**
- Set **who can comment or view comments** (e.g. everyone, only Admins)
### Notifications
Your app users can toggle Notifications on and off on the comments if they want to be notified by email when a new comment occurs on an item. You can also customize the notification emails that are sent to your users in the Notification section of the Comment Settings menu.

---
# Use Case: Creating a User Profile with Item Details
Source: https://docs.softr.io/building-blocks/use-case-creating-a-user-profile-with-item-details
Here, we are going to create a user profile section using the List Details block, which will let each logged-in user see their own data.
First of all, we need to have a [users Airtable base linked](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/syncing-users-with-a-data-source/hshRGygHr4T33EnaLntGf9) in Users section. Below, we have a list of users from [Airtable](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX).

_Users' Airtable base_
Then, we are going to create a separate page (called "My Profile"), add a List Details block there, and link it to the same Users base and table in Airtable. Moreover, we are going to define a conditional filter so that a logged-in user sees the record where the **Email** matches his/her **Email value**.
> **Tip**
>
> Please, note that if there are multiple records that meet the defined condition, the **first**
> record in the list will be shown.

_Details block linked to the Users' base with conditional filter_
So, that's the setup. Now, any logged-in user that opens the My Profile page, will see his/her own profile info. The process is shown below.

_User seeing his/her profile_
---
# Use Case: Embedding Calendly in List Details
Source: https://docs.softr.io/building-blocks/use-case-embedding-calendly-in-list-details
First of all, you need to get your Calendly embed code, as described [here](/custom-code/3idxDhKqz1qPdqBuWbs61G/custom-code-block-overview/6XNrxFopUEiwbWipq81Eq1). Further on, create a corresponding field in your [data source](/4230abecf813402aa2926466c313290a) that you're using for the List Details block. In the example shown below, we've created a **Single line text** field named "Calendly" in [Airtable](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX) and added the embed code to one of the rows.

_Adding embed code to Airtable_
Next, we’re going to add an **Embed** type field to the List Details block and link the "Calendly" field from Airtable.

_Adding the embed field_
That's it. Now the Calendly embed will start appearing on the list item as shown below.

_Calendly widget added on List Details_
# Other Integrations
You can embed other publicly accessible integrations this way as well. Some ones we’ve seen aside from Calendly are Trello cards, Google Docs, YouTube videos, and Github issues.
---
# Use Case: Filtering other lists by a list detail block’s data
Source: https://docs.softr.io/building-blocks/use-case-filtering-other-lists-by-a-list-detail-block-data
> **Tip**
>
> Before you begin, make sure you have a good understanding of the [Core Concepts of Softr](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx).
## Use Case
You can use the data available in a list detail block to filter other lists on the same page. This is incredibly helpful in a variety of situations:
- Filter a list of line items that belong to an order
- Show a list of tasks that belong to a project
- Display all of the contacts that belong to a selected company
- Show all files uploaded by a specific user
- … and many, many, many more.
## Setup
### Creating the main list
This list will serve as the main record type the user will be selecting and can live on any page in your app. In the example below, we have a very simple Home page with a simple card list of Projects being pulled from Airtable. The cards have an action setup that when a user clicks on a card, it takes them to a details page in the app called “Project details”.
You can use any type of list, table, or even Calendar and Kanban blocks for this. Anywhere you have records listed, you can link to a details screen.

### Creating the list details page
When you set up the main list and create the “on click” action, you will be asked to link to a details page for that item. If one doesn’t exist, you can also create one. In the example below, we have a “Project details” page with a very simply Item Details block showing the project image, name, client name, and status. You’ll notice that Softr prompts us with a dialog at the bottom of the screen to add items that may be linked to a project such as Tasks and Users.

### Adding linked lists
We can either click Add in the dialog at the bottom of the page or we can also add lists to the page manually, which is what we will do here. Below you can see that we added a “List with small cards” block below the detail block for the project and set the source to be “Users”.
We also added a conditional filter stating that we only wanted to see Users where their “Projects Assigned” includes any of the Current Record’s → Project Name. This will ensure that no matter which project is selected from the main list, this list of team members (Users) will only show the people who have been assigned to the specific project, regardless of which project is being viewed.
> **Tip**
>
> Note that the editor will not show live filtered data, only test data. If you want to test the filtering, be sure to [Preview the app](/publishing/9qTmU2Lj8Gnpr1Ue6dEAkX/publishing-your-softr-app/gRrb1u7eLmRTrXyg3UNGkQ#previewing-your-softr-app) as different users!

Now let’s add one more linked list to view the Tasks associated with this project detail. Below we added a basic “Table” block with the source set to Tasks and also added a conditional filter stating that we should only show Tasks where the Project Name is the same as the Current Record’s → Project Name. This ensures that only tasks belonging to the selected project are seen here in the table.

## FAQ
Click on a toggle to reveal the answer.
**Can I have multiple list details blocks on the same page?**
Yes! But linked lists will only ever be able to filtered by the first list detail block at the top-most part of the page. If you need to filter multiple lists by different type of records and list details blocks, we recommend creating separate pages for that.
**My list is saying no items found, what can I do?**
Conditional filters are case and field sensitive, so make sure your conditional filters make sense. For example, if you’re matching Project Name with a task’s Project Name, make sure those two values are actually the same in your data source.
**Is there a limit to how many linked lists I can have on a list detail page?**
No, but from a user experience standpoint, it helps to make use of our [Tab](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/tabs/38PkeKBDeLtiKuCXp7YeBr) and [Column](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/column-container/t7HCEKvV6Y5y2t3hSWwRNx) container blocks to keep your page neat and organized!
**Can I do this with charts as well?**
Absolutely!
**I need people to see more details about an item in a linked list, what can I do?**
The same as the main list, you can add a details page for items in linked lists that people can click on to see more info, either by linking to a new page, opening a modal, or even linking out to an external URL.
**Can I let people edit or create records using the current record’s data?**
Yes, you can use Hidden Fields to capture information about the current record and save it as part of a different record type. Check out [this example of a Job Submission form](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/use-case-job-submission-with-hidden-fields/9j4RWhci9bi3o4BCTt6mRW).
---
# Use Case: Hiding blocks based on current record data
Source: https://docs.softr.io/building-blocks/use-case-hiding-blocks-based-on-current-record-data
## Use Case
Not only can you change a block’s visibility based on the User Group that a logged-in user is in, but you can also control a block’s visibility based on a currently selected record. This is great for:
- Showing different line item formats on an invoice depending on the deal type
- Showing or hiding a request form based on the type of document being viewed
- Showing or hiding different task views based on the project type or a project owners preferred task view.
- Displaying different CTAs based on a selected record
- …and much, much more.
## Setup
In the example below, we want to conditionally show a request form, based on if a selected document is available to request or download. If the document has a file field that is not empty, we should only show a button to download and hide the form. If the file field is empty, we should show a form that allows end-users to request this file via email instead. This allows an administrator to track who has been given access to particular files and see how many times they have been accessed.
### Hiding the Download Button
We need to hide the download button if the file field is empty. First select the block, go to the Actions tab, and select the Download button. Then click on the little branching icon in the button settings:

Once open, we can toggle on the “On Specific Records Only” button and setup some rules to hide the button if the File field is empty.

### Hiding an entire block based on current record data
Since the item details block is showing only one specific record, we can use that record’s data to determine whether or not to show other blocks on the page. For our example, we want to hide a Request Form if the File field in our database (you may have other fields and field names you want to use).
First, select the block, then click on the Visibility tab and turn on the “Hide if” toggle. Setup your rules, which in our case should be If the File field “Is not empty”.

---
# Table Block
Source: https://docs.softr.io/building-blocks/table-block-
The **Table block** presents a collection of records, such as tasks, products, or contacts, in a structured table layout. This format is particularly effective for displaying data with multiple fields, allowing users to efficiently compare, sort, and manage large sets of information efficiently. Each record is organized into rows, while columns represent fields like name, date, tag, or status. Tables are interactive, supporting the sorting and filtering of data.

## **Use case examples**
- **Client Profiles:** Display detailed customer information, including name, company, contact details, last interaction date, and associated account manager. Enable filtering by account status (active, inactive, etc.).
- **Invoice Management:** Provide clients with a table of invoices showing invoice numbers, issue dates, due dates, amounts, and payment statuses. Clients can sort by due date or filter unpaid invoices.
# Configure a Table block
> **Tip**
>
> **Build with AI:** Instead of configuring manually, you can add a Table block instantly with the **AI Co-Builder**. Just click the AI icon in the editor and type: _"Create a table of customer support tickets showing status, assignee, and date."_
## Source
The **Source** panel connects the list block to your data source. Here, you can:
- Connect the list block to your[data source](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/connect-your-data-source/41p6U2eZs6NZ5qZp7iKvnn).
- Set up[conditional filters](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/conditional-filters/mDnn7jnpPiYmJcT99jpt7m) to display only the data that meets specific criteria.
- **Define sorting rules** and set the number of items to display per page.
- **Customize the empty state message** that appears when no data matches the requirements.
Once you connect to your source data, you can configure Content, Actions, and block Visibility settings.
> **Info**
>
> Some configuration options depend on the [data source](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/connect-your-data-source/41p6U2eZs6NZ5qZp7iKvnn). For more details, check the documentation for your specific data source.

## **Content**
In the **Content** tab, customize fields in your table block, adjust their display, and add features like search and filters to help users find information quickly.

_The Content tab of the Table block._
### **Item fields**
**Item Fields** lets you connect fields from your **data source** to each list item, making it easy to display the information you need. You can control what information appears by adding, removing, or rearranging fields such as task names, assignees, or descriptions.
For each field in the **Item Fields** section of the secondary section, you can customize the following options:
- **Type:** Defines the display field type that controls how content appears in the block (e.g., text, checkbox, or image).
- **Content:** Chooses the specific data field from connected data sources to display.
- **Label (Optional):** Adds context to the field. If left blank, the label will not be visible to users.

> **Info**
>
> **Note:** Some display field types are compatible only with specific data formats. For example, if a field is set to display images, you cannot map it to text data. Ensure the field type matches your data source field format to avoid display issues.
**Supported field types**
| | |
| ----------------- | --------------------------------------------------------------------------------------------------------- |
| **Display Field** | **Description** |
| **Text** | Displays plain text. Ideal for names, titles, or short descriptions. |
| **Rich Text** | Supports long text, markdown, or HTML formatting. Allows for more detailed descriptions or notes. |
| **Email** | Displays email addresses as clickable mailto links, allowing users to start an email directly. |
| **URL** | Displays website links as clickable URLs, allowing users to navigate to external pages. |
| **Tag** | Allows you to display one or more tags, helpful for organizing items by category or status. |
| **File** | Provides a link for users to download attachments, such as PDFs or other documents. |
| **Video** | Embed video content from a supported source, allowing users to watch content directly in the block. |
| **Image** | Displays a single image, useful for things like profile pictures or product images. |
| **Image gallery** | Displays multiple images in a gallery format, useful for showcasing a collection of visuals. |
| **Embed** | Allows you to embed content from other services, such as YouTube videos, Calendly, or social media posts. |
| **Rating** | Displays a rating system, typically with stars, to visually represent ratings or scores. |
| **Checkbox** | Shows a checkbox, useful for indicating completed items or allowing users to mark items as done. |
### Inline Editing
You can enable **inline editing** for fields within the Table block, allowing users to update data directly in the table—no extra action buttons required.
**How to Set Up Inline Editing**
1. Identify which fields should be editable directly in the table.
2. In the individual field settings, toggle the **Allow editing** option to enable editing.

1. **Configure** how users interact with editable cells:
- Input Field Type – Choose the input type users will see (e.g., short text, long text) and configure any additional options based on the selected type.
- Placeholder – Provide guidance for empty fields; this placeholder appears when users click to edit a cell.

👉 Preview the table to see the user experience—just double-click a cell, edit the content, and press Enter to save.

### **Search bar**
The **Search Bar** allows users to search through items in your block, making it easier to find specific entries quickly.
You can configure which parameters you want the search to be performed by adding fields to Search by input. For instance, if you’re displaying a list of employees, you might select “Name,” “Department,” and “Job title” as searchable fields.

> **Info**
>
> If no fields are selected, the search bar will display all items regardless of the search term. To ensure meaningful search results, always select at least one field.
## Actions
[Actions](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/actions-adding-and-editing-data-/41p6U2eZs87asLz6dV5AMy) let you define what happens when users interact with a block, such as navigating to a new page, editing records, or triggering workflows. This ensures your app not only displays data but also offers dynamic user engagement.

**Topbar buttons**
- [Add record](/actions/ntEfT9zSJk6aY54G6W5KGU/add-record/3LrUMpQY4BKfDDQj6eb8h8): Create new entries in your data.
- [Open page](/actions/ntEfT9zSJk6aY54G6W5KGU/item-on-click-actions/f1ns7phZfNNvgwXA6tTN3M): Navigate to another page within your app.
- **Open URL**: Redirect users to an external link.
- **Scroll to**: Move the view to a specific section within the block.
- [Export](/actions/ntEfT9zSJk6aY54G6W5KGU/export/mnrvzncWeoSfwWJscZCAxC):Export visible records.
**Item buttons**
- [Edit record](/actions/ntEfT9zSJk6aY54G6W5KGU/edit-record/irSJXPF1gCMXNmfsQFscvx): Modify the details of a specific record.
- [One-Click Update](/actions/ntEfT9zSJk6aY54G6W5KGU/one-click-update/8BaX5i6KLZhZCrSZERGnej): Apply predefined updates to a record with a single click.
- [Open details page](/actions/ntEfT9zSJk6aY54G6W5KGU/item-on-click-actions/f1ns7phZfNNvgwXA6tTN3M): Open the details page of the selected record.
- [Delete Record](/actions/ntEfT9zSJk6aY54G6W5KGU/delete-record/peV9LGdJbM9sKHKynqopkH): Remove a record from your data.
- **Open URL**: Redirect users to an external link.
- [Download file](/actions/ntEfT9zSJk6aY54G6W5KGU/download-file/8Sr2y4CREVcW2GEEDYUhfJ): Provide users with a direct option to download associated files.
- [Call API](/actions/ntEfT9zSJk6aY54G6W5KGU/call-api/i9f1s3w9wib3oRmS4HZ7MX): This action triggers a custom API call for advanced integrations (_available for Professional, Business, and Enterprise plans)._
## Visibility
Control who can see a block by setting up [visibility](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/block-visibility/3spA2dfQNrcGcPNmnDXHB3) rules. This helps tailor the user experience by showing relevant content to the right audience, improving personalization and security.

## Style
Customize the look and feel of your blocks with s[tyling](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/style-your-app/41p6U2eZs8AZmBW8mHykXA) options. Adjust fonts, colors, spacing, and more to align with your app’s branding and create a polished, professional design.

## Relevant Guides
- [How to set up a record detail page?](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/item-details-block-/4bE8XaFbJp45wkAwuWiz8f)
- [How to filter list records by Page URL parameter?](/how-to-guides/ioi5BbuQ2RDM7aHPrpXnjG/how-to-filter-list-by-page-url-parameters/42JZoeYwMstwaL9aoBdRjz)
---
# Conditional Forms
Source: https://docs.softr.io/building-blocks/conditional-forms
Conditional Forms include all the features of Basic Forms but are enhanced with advanced functionalities like Step Logic, Section Logic and Dropdown option filtering (based on logic). These features enable the forms to adapt in real time to the attributes or input of your form users, creating a tailored form-filling experience.
## **Building a Conditional Form**
Setting up a Conditional Form involves the same initial steps as setting up a Basic Form. Here’s a quick recap:
> **Tip**
>
> **Build with AI:** You can skip the manual setup and instantly generate a conditional form with the **AI Co-Builder**. Open the AI chat and try: _"Create a multi-step job application form that asks for additional portfolio links only if they select 'Designer' as their role."_
1. **Add a form block preset**: From your Softr app, add a new form block to your page.
2. **Select a destination**: A destination can be a data source, email or a tool like Zapier or Make. You can also send a predefined JSON body directly to a webhook.
3. **Add questions**: Add and map the required fields into your form such as Name, Email, Message, etc.
### **Step logic**
Step logic allows you to guide users through specific steps of a form based on their inputs or predefined user attributes. Here’s how to implement it:
1. **Add steps**: Break your form into multiple steps or pages.
2. **Set conditions for paths after a step**: Specify conditions under which a user should be directed to a particular step. For example, if a user selects "Yes" to needing additional services, you can set the form to navigate to a step that gathers more detailed information about their requirements.
3. **Test step logic using preview mode**: Ensure that each pathway functions as intended by testing each conditional route to catch any errors or logical inconsistencies.
### **Section logic**
Section logic enhances the adaptability of forms within individual steps:
1. **Add sections**: Divide your form into sections within a single step, grouping related fields together.
2. **Apply conditions to sections**: Configure each section to show or hide based on user responses or attributes. For example, a section asking for payment information can be hidden unless the user selects a paid service.
3. **Dynamic sections**: You can make sections dynamically appear as more information is required or certain conditions are met, improving form engagement and preventing information overload.
### Dropdown options filtering
Dropdown options filtering allows you to conditionally display specific values in a dropdown field based on certain criteria. This is particularly useful when you want to guide users to select only relevant options.
**Linked record option filtering**
Imagine you have an event registration form connected to your "Registrations" table, which in turn is linked to an "Events" table. Each event in your data source might have a status of either 'Upcoming' or 'Past'. To prevent users from registering for 'Past' events, you can filter the dropdown to only show 'Upcoming' events. Here’s how to set it up:
1. Add the dropdown field: Insert a dropdown field in your form and map it to the 'Event' field, which is a linked field from the "Registrations" table.
2. Access the option filter: Click on the logic icon next to the “Options” label. This will open the option filter panel.
3. Apply the conditional filter: Toggle on the "Filter options by condition" setting and add a condition. For this example, you’ll filter by `Status is Upcoming`.
With this setup, the dropdown will only display 'Upcoming' events for users to select, ensuring that they can’t mistakenly register for past events.
This example demonstrates how to filter linked record options.
**Option value filtering**
You can also apply filters based on the option values themselves, providing flexibility for different scenarios. For instance, imagine you have an email field in your data source that’s mapped to a dropdown field. If you only want to display email addresses that belong to a specific domain, such as '@softr.io', you can filter the dropdown options to show only those emails. This ensures that users are restricted to selecting emails that match the specified criteria.
### Ending Logic
You can control what happens when a user submits the form based on conditional logic. There are two parts to setting conditional endings: the ending itself and how users arrive there. One ending is always provided for you by default and you must have at least 1 ending on every form.
To access the Endings, select the form block and click on the **Questions** tab.
**The Form Ending**
1. **On Submit** - You can choose to either show a success message or a thank you screen. For success message you can customize what it says. For the thank you screen you can customize what the thank you popup modal says.
2. **Success Message/Thank You Screen** - This section will change based on your choice, allowing you to change the success message or thank you screen respectively.
3. **Action** - Here you can choose what should happen when the user submits the form. Choose from the following options:\
1. Refresh form - This will start the form from the beginning and let the user start a new submission
2. Open details page - This will open a details page for the newly created record. If one doesn’t exist, you can create one.
3. Open page - This will open a page in your app that you specify.
4. Open external URL - This will send the user to a link or URL that you specify.
4. **+ Add ending** - This will add another ending to your form that you can use conditional logic to direct form submissions to.

**Adjusting the Logic**
Much like adding steps to the conditional form, you can select steps and use paths to send users to different endings.
1. Click on the Logic tab to open up the form Logic Builder.
2. Select the Step you want to route to an ending.
3. Apply any logic that should make this path function and choose the Ending you want.

---
# Advanced Form Features
Source: https://docs.softr.io/building-blocks/advanced-form-features
## Destination
In this section, you customize the form and set where it's going to be sent. To start configuring the form fields, you first need to set the form's **Destination**.

_Form destination_
Here, you have the following options:
- [Send to data source](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/tutorial-sending-form-data-to-a-data-source/pgX6BhyR98bLopZtgsXMwU)
- Add to [Mailchimp](/integrations/etS18kJqm1fuD58KCsjC3z/mailchimp/2GvSLRGrgMfe8S3drMWao1)
- Add to [Mailerlite](/integrations/etS18kJqm1fuD58KCsjC3z/mailerlite/i1Ex2KK1HwqsceB1SnYWby)
- Send to [Zapier](/integrations/etS18kJqm1fuD58KCsjC3z/zapier/vFrfgfV12U9F9SNqbrAHLd)
- Send to [Make](/integrations/etS18kJqm1fuD58KCsjC3z/make/dNDFZTp7eeNj7HnaUV6YMa)
- Forward to your email
You can learn more about each option under its respective article (links added above). And you also have the **Forward to your email** option, which simply sends the submission to the specified email address. So, let's select the **Forward to your email** option and go over the fields types and their settings.
## **On Form Submit**
After the form is submitted, you can either display a success message or take the user to a different page.
### **Success Message**

_Configuring the success message_
You can customize the message as well as configure styling and formatting.
### **Open Page**

_“Open Page” option_
Just select the page, and the user will be taken there after successful submission.
## Field settings

_Field settings_
All the field types (apart from **Hidden Fields**, which we'll consider separately), have the following common settings:
- **Label** – a label for the field (appears above or next to the field depending on the form layout)
- **Placeholder** – placeholder text for the field
- **Field** – a unique identifier (i.e. name) for the field
- **Required** - is the user required to fill in the field or not
Now, let's see what field types are available:
- **Email** – a field where users can enter their email address
- **Text/Long text** – for single/multiple line texts
- **URL** – for submitting a URL
- **Phone number** – here users can provide their phone numbers. Please, note that validation is applied on entered phone numbers
- **File** – a field where users can upload files
- **Date** – a date field where users can choose a date from a calendar pop-up
- **DateTime** – allows providing date and time within a single field. Can be mapped to any text type field in Airtable (e.g. Single Line Text)

_DateTime field_
- **Checkbox** - a checkbox field with a yes/no value. If you are mapping the field to Airtable, you need to use a "Checkbox" field type there as well.
- **Rating** - allows submitting a rating (1-5 stars). If you are mapping the field to Airtable, you need to use a "Rating" field type there as well.
- **Address** - this is a regular text field, where users can enter their address, but it also has **address autocomplete**. However, to enable autocomplete, you first need to integrate Google Maps in **Settings => Integrations => Google MAP**. Follow the instructions [here](https://developers.google.com/maps/documentation/javascript/get-api-key), to get the map API key
- **Hidden** - described below separately
- **Number**
- **Dropdown** – a dropdown where users can select one of the provided options. Here, you also have the **Options** parameter, where you can list all the options separated by a semicolon (**without spacing**).

_Dropdown field type_
If you’ve mapped the dropdown field to a **single- or multi-select field** in Airtable, a **Sync options with data source** will appear, which lets you sync all the values from Airtable automatically instead of adding them manually.

_“Sync options with data source” toggle_
- **Multiselect Dropdown** – similar to **Dropdown** but with the possibility to select more than one option
For dropdowns, you can also toggle to enable users to add additional options if the one they are selecting does not exist yet. This is great for adding additional selection options. Note that this is not yet possible for linked records in a dropdown.

### **Signature field**
> **Note**
>
> **eSignature capture** is available for the users on the [Professional plan and above](https://www.softr.io/pricing).
This form field allows users to either type or write their signature (using finger on a touch device or mouse on desktop). The signature is then saved as an image in your data source (e.g. in a File field in Softr Databases, an Attachment field in Airtable, or as an image URL in Google Sheets).

_Signature field selection and draw or type option modals_
> **Info**
>
> Images on the records can serve as a reference for anyone entitled to access that record. It is important to ensure that your record-keeping practices meet any specific legal requirements for your industry and jurisdiction. [Read more](https://www.pandadoc.com/electronic-signature-law/) about electronic signature laws across countries.
### Hidden field

_Hidden field settings_
This field type allows sending hidden data that the user doesn't see (you can find a use case [here](https://developers.google.com/maps/documentation/javascript/get-api-key)). There are **4 categories**, so let's examine them one by one.
**1. Logged-in user**
By default, here, you have the following options:
- **Email.** Collects the email address of the logged-in user.
- **Name.** Collects the name of the logged-in user.
- **Record ID.** If you've [connected a data source to your users database](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/syncing-users-with-a-data-source/hshRGygHr4T33EnaLntGf9), you can choose this option to collect the Record ID (you can learn about [Airtable](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX) Record IDs [here](https://developers.google.com/maps/documentation/javascript/get-api-key), and learn how those work for Google Sheets [here](https://developers.google.com/maps/documentation/javascript/get-api-key)) of the user.
**2. URL Parameter**
Using this option, you can collect any of the page’s URL parameters. Let's consider a specific example to see how that works. For instance, if you've created a job board with Softr, each job announcement will have a **recordId** (you can learn about [Airtable](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX) Record IDs [here](https://developers.google.com/maps/documentation/javascript/get-api-key), and learn how those work for Google Sheets [here](https://developers.google.com/maps/documentation/javascript/get-api-key)) in its page URL, indicating the [data source](/4230abecf813402aa2926466c313290a) record corresponding to that particular job. So, if you have a form on that page to receive job applications, you can set a hidden field to collect the **recordId** to identify which job announcement the application has been submitted for.
Your page URL will look something like **yoursite.com/job-details/senior-product-manager?recordId=rec7HcXAgKmlk8inf**, so if you set your hidden field value as “**recordId,”** it will collect the value of **recordId** ("rec7HcXAgKmlk8inf" in this case).
**3. Page URL**
This parameter allows to get **the full URL of the page** the form has been submitted from.
**4. Custom value**
Here’ you can collect any custom value that you’re not able to collect using the previous options. For instance, you can use it to collect a custom text along with the submission. This can be useful is you have the same form on different pages, and want to mark each of the forms distinctively.
Another important use case is collecting additional logged-in user parameters. If you've [synced your users database with a data source](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/syncing-users-with-a-data-source/hshRGygHr4T33EnaLntGf9), you can use this option to collect any of the field values corresponding to the user. Here, the value has the following format:**\{LOGGED\_IN\_USER:FIELD:'field name'}** ('field name'is replaced with the actual name of the field).
Let's say you have connected an [Airtable](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX) data source and have a **Status** field in your users base as shown below.

_Users Base on Airtable_
So, if you set your hidden field's value as **Status,** the values of the **Status** field will be collected for each user submitting the form (e.g. for Elise it will be "Active").
## Form Prefill
Using this feature, you can send your Softr form to others with one or more fields prefilled with values. Let's see how that works.
Let's say your form URL is **yourdomain.com/form**. To prefill a certain field for this form, you need to add a parameter to your form URL and assign a value to it in the following format:
> **?prefill\_tagname=value**
> **Tip**
>
> If it's the first parameter in your URL (e.g. you could already have other parameters not related to the prefill), it needs to start with "?." However, if you already have other parameters in the form URL, attach the new ones using "&" at the beginning: **\&prefill\_tagname=value**
For instance, if you have a text field with a **Tag** "NAME," and you want to prefill it with "John," your URL will look as follows:
> **yourdomain.com/form?prefill\_NAME=John**

_Text field settings_
> **Tip**
>
> Please, note that the **Tag** value is case-sensitive and should match exactly the value in your field settings.
Below, you can see what we described in action.

_Prefilling the name field_
If the field type receives a single value and doesn't have any special formatting involved, it can be prefilled in a similar way. **Hidden fields** work the same way as well.
> **Tip**
>
> Please, note that the **File** field type is not supported.
Further on, if you need to prefill **multiple fields**, just add the new values next to each other as shown below:
> **?prefill\_NAME=John\&prefill\_Email=**
Now, let's see how prefill works for the field types that receive their values differently.
### **Multi-select Dropdown**
Here, list all the preselected values in a **single** parameter, separated by semicolons with no spaces:
> **prefill\_Option=X;Y**

_A multi-select field prefilled with two values from the URL._
> **Warning**
>
> The semicolon is the only separator that works. A comma (**prefill\_Option=X,Y**) matches no option and leaves the field empty, and repeating the parameter (**prefill\_Option=X\&prefill\_Option=Y**) applies only the last value. A space after the semicolon (**X; Y**) silently drops everything after it.
> **Note**
>
> Prefilling more than one value also needs the form field itself to accept more than one. In the block’s **Steps** tab, open the field, expand **Selection**, and switch on **Allow multi-select** — otherwise only the first value in the list is applied.
### **Date and DateTime**
You can use a date like `?prefill_date=2024.10.25`. But it’s not limited to this format; since we’re using [JavaScript’s Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) object, you have a broad range of formats to choose from, like `2024/10/25` or even `October 25, 2024`. You can also pre-fill with date and time, like `prefill_date=2024.10.25 15:30`. If the pre-filled date or datetime is invalid, nothing will be displayed. Some examples:
> **?prefill\_datefield=dd/mm/yyyy**\
> **?prefill\_datetimefield=mm-dd-yy HH:MM**
> **Tip**
>
> Since the time picker has fixed values available for selection (e.g. 01:30 or 16:00), you should use the same values when setting the prefill for the DateTime field.
### **Checkbox**
For the checkbox type, you can set the value as "true" (use lowercase only) if you want it to be pre-checked:
> **?prefill\_checkbox=true**
That's it. Now, you should be able to send your form URL to your users with any of the fields prefilled with your preferred values.
> **Tip**
>
> Email marketing services (e.g. [Mailchimp](/integrations/etS18kJqm1fuD58KCsjC3z/mailchimp/2GvSLRGrgMfe8S3drMWao1)) often provide variables that you can use as values in your prefill configuration to be able to send the form URL to a group of users at once so that each user has his/her own info (e.g. Name, Email, etc.) prefilled.
## **Enable reCaptcha**
By adding reCaptcha authentication to your form, you'll protect it from getting spammed or misused.
> **Tip**
>
> Please, note that Softr only supports [reCaptcha v3](https://developers.google.com/recaptcha/docs/versions).
> **Note**
>
> For reCaptcha to be enabled the app needs to be published.
To set up reCaptcha, you need to go to and enter your site details as shown below.

_reCaptcha setup_
In the next screen, you just need to copy the **Site Key** and **Secret Key.**

_Getting Site Key and Secret Key_
To finalize the setup, paste the Site Key and Secret Key in your Softr app's **Settings => Integrations => Google reCaptcha.**

_Adding reCaptcha keys_
## **Using Forms on Details Pages**
Conditional forms can be particularly powerful when used on details pages, where the form's behavior can depend on specific data from a list details record. To ensure that these forms operate correctly, special attention must be given to how data fields are mapped and utilized within the form.
### **Setting up Forms on Details Pages**
When adding a conditional form to a details page in Softr, the form can interact dynamically with the data displayed on that page. This setup allows you to create forms that respond and adapt based on the specific details of the record being viewed.
### **Field mapping and conditions**
To utilize record-specific data in your conditional logic:
1. **Data mapping**: Ensure that any field used in the form’s conditions is corresponds to a mapped field in the list details block. This mapping is crucial because it allows the form to access the relevant data to evaluate conditions correctly.
2. **Configure conditions**: When setting up conditions in your form that depend on list details, refer directly to the mapped fields. For example, if you have a form on a real estate listing page that should display additional questions about mortgage options only if the property price is above a certain value, you must map the property price field from the list details to the form.
3. **Validate field mapping**: Verify that the fields used in your conditions are not only mapped but also correctly pulling data from the list details. If the field isn’t mapped, the conditional logic based on that field will not function, potentially causing the form to behave unexpectedly.
### **Testing and troubleshooting**
- **Testing**: Thoroughly test the form by navigating through different records on the details page to ensure that the conditional logic triggers as expected for different data scenarios.
- **Troubleshooting**: If a condition doesn’t work, double-check the field mappings and the logical statements used in your conditions. Ensure there are no discrepancies between the field names in the database and those referenced in your form settings.
---
# Use Case: Job Submission with Hidden Fields
Source: https://docs.softr.io/building-blocks/use-case-job-submission-with-hidden-fields
Here, we'll go through a use case when incorporating hidden fields into your form can be useful.
Let's say you have a job board (built using a [List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU) block in our case), which is in turn connected to a [List details page](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/item-details-block-/4bE8XaFbJp45wkAwuWiz8f) for displaying the complete overview of the position. Apart from job details, the details page also contains a form through which visitors can apply for that job. The blocks display data from a [data source](/4230abecf813402aa2926466c313290a), which in this case is [Airtable](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX). Below you can see what these pages and their corresponding Airtable tables look like.

_Job board and job details_
This way, each form submission will be stored under the **Job Submissions** table. However, since we don't have a field where the user can select which position he/she is applying for, we can't associate the submissions with their related jobs. But instead of adding such a field, we can go one step further and link each form submission to its related job entry in the **Jobs** table. This is where hidden fields come in handy.
First of all, let's link the two tables through a linked record.

_Linking 'Jobs' and 'Job Submissions' tables_
Now, on our form, we'll add a [URL parameter](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/advanced-form-features/jCim5VWZePgZuaRsUZBnpG) hidden field that gets the **recordID** of the page it has been submitted from and map that field to the **Jobs** linked record field we just created. As a result, Airtable will locate the corresponding job record from the **Jobs** table and link it to each new job submission.
Now, on our form, we’ll add a Hidden field input that is Mapped to our new Jobs field in the Job Submissions table. Since we are linking to the list details page from our list of jobs, we can choose information from the Current Record to be saved as the value of our hidden field. We can use the primary field (first column) from the Jobs table as the value to send in the Hidden field. In this case it’s the Name of the job.

That's it. As you can see, the job submission is successfully linked to its related job record. Whenever a user submits an application on a job’s detail page, the form will automatically link to the job the user is applying for.
---
# Tutorial: Sending Form Data to a Data Source
Source: https://docs.softr.io/building-blocks/tutorial-sending-form-data-to-a-data-source
Here, we will go through the process of creating a form within a Softr app and linking it to a [data source](/4230abecf813402aa2926466c313290a) (we’ll use [Airtable](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX)) to collect form submissions there. We will create a job posting form, where users will be able to submit job announcements along with all the necessary fields such as description, location, type, and others.
## Creating the form
To add a form, we need to add a new block, selecting the [Customizable Form](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/advanced-form-features/jCim5VWZePgZuaRsUZBnpG) or the [Customizable Form with Labels](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/conditional-forms/afyKqnGDXd54U8d4xLNcsR).

_Selecting the Form_
## Selecting a destination
First, we need to choose where the form is going submitted to. The **Destination** is located under the **Features** tab of block’s settings. We’re going to choose the **Send to a data source** option and select Airtable. Afterwards, we also need to select the **Base** and **Table** that needs to be linked to our form.

_Configuring the form destination_
> **Tip**
>
> To be able to select a data source you need to connect it from **Settings ⇒ Data Sources**. You can find more info on that in our step-by-step guides for [Airtable](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX) and [Google Sheets](/data-sources/1YYStCJukT15Lh2j93qo9A/google-sheets/jznC9Jr3Jri224AVmHVn4a).
Now, let’s see how we can customize the form to start getting job announcements.
## **Customizing the Form**
Let’s customize the form to include all the fields necessary for our job postings. In our example, those include such fields as **Company Name**, **Logo**, **Job Description**, and so on.
For each field you need to select a relevant **Type**. For fields that require the user to type in the value, you can choose **Single line text** or **Long Text** (suitable for the **Job Description** field in our example). For the fields that require uploading a file (e.g. **Logo**), we will select the **File** type, and for the fields that are going to have a predefined list of options to choose from, we are going to set the type as **Dropdown**. For **Dropdown** fields we are going to add all the available options inside **Options** separated by a semicolon. In the screenshot below you can see the job category field with its options.

_Dropdown field setup_
Apart from the field type, we can also add a **Label** and **Placeholder** text. Further on, we need to pay particular attention to the **Map to** field, which indicates the data source field that the give field should be linked to.
Below, you can see how we’ve linked the Category field to its corresponding field on Airtable.

_Mapping the Category field_
To be able to map all the fields, we need to have them ready along with their relevant types (there are no field types in Google Sheets, so you can find out how to handle such cases [here](/data-sources/1YYStCJukT15Lh2j93qo9A/google-sheets/jznC9Jr3Jri224AVmHVn4a)), which we’ll look into next.
## Preparing the Airtable database
In our Airtable base, the fields (base columns) need to correspond to the form fields in the Softr app. The column name needs to be the same as the field’s tag within the form, and their types need to match as well. In Airtable, we have similar field types:
- **Single line text**
- **Long text**
- **Attachment** (corresponds to **File** in the form)
- **Single select/Multiple select** (correspond to **Dropdown** in the form)
In the following screenshot, you can see the “Category” field along with its field type and available options.

_Category field on Airtable_
Thus, as soon as we have our Airtable base ready, we can proceed with linking it to our form by selecting the **Base** and **Table** as described above.
## **Publishing the Form and Testing**
That’s it. Our form is ready, and all we need to do is to publish it and do a test submission. If the test is successful, a new row with the form submission should be added in the connected Airtable base. Below, you can see the test data filled in inside the form and how it looks after being submitted to Airtable.

_Test data filled in the form_

_Submission added in the Airtable base_
---
# Chart Block Overview
Source: https://docs.softr.io/building-blocks/chart-block-overview
> **Note**
>
> Chart block is available for users on the [Professional plan and above](https://www.softr.io/pricing).
Using the Chart block, you can add different types of charts to your Softr app. The charts get the data from [data sources](/4230abecf813402aa2926466c313290a).
In the following articles, you can get familiar with different chart layouts that are available. In this article, we’ll set up a chart (using a **Bar Chart** as an example) from the scratch and explain each configuration option.

_A dashboard built with the Chart block: Metric (1), Column (2), and Donut (3) types._
To start configuring the chart, you first need to link it to a [data source](/4230abecf813402aa2926466c313290a) to start displaying your data. We are going to use [Airtable](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX) for that purpose. So, let’s start.
> **Tip**
>
> If you make an update in your data source, **it will take 15 min** until that change is reflected in your chart in preview, and live mode.
>
> Learn more about data sampling and data freshness at the end of this article.
## Linking a data source

_Linking an Airtable base and table_
This part is similar to the [List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU) block settings, where you need to connect a data sourcefrom the **Data** tabto get your chart data.
> **Tip**
>
> Please note, that you first need to have your [data source](/4230abecf813402aa2926466c313290a) linked in **Settings => Data Sources** to be able to connect a specific database.
### Conditional Filters
Under the **Source** tab, you also have the **Conditional Filters** section. Chart **Conditional Filters** work similar to [List conditional filters](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/conditional-filters/mDnn7jnpPiYmJcT99jpt7m).

_The Record filters section of the Source tab: add conditions to show only some records._
> **Tip**
>
> If you want to refer to an Airtable Linked Record in your condition, use a relevant **Lookup Field** (supported), not a Linked Record itself (not supported).
## Features
Now, let's see what we have in the **Features** tab of block's settings.

_The Content tab of the Chart block: type, title, metric, and grouping._
### **Title and Subtitle**
### **Type**
Next, you have the **Type** parameter where you select between different chart types. Let’s select the **Bar Chart** type and move on to configuring our data.
### Metrics
As you can see, each record has a **Type** field, a **Sub-type**, and a corresponding value, which is negative in case of expenses.
Let’s say we want to display the sum of incomes and expenses for each month.
For that, we have to define what is our metric. In our case incomes and expenses are stored in Airtable **Value** field, and the metric should be a sum of those.
The **Aggregate function** has the following options:
- **Sum**. Calculates the Sum of all the values for a given category.
- **Average**. Calculates the average of all the values for a given category.
- **Min**. Picks the smallest value of all the values of the category.
- **Max**. Picks the biggest value of all the values of the category.
- **Count distinct values**. Adds up the number of records that **contain a unique value**.
- **Count all**. Adds up the number of records present in a given grouping category.
### Groupings
Now, let’s explore each setup option in greater detail.
**Time interval**
For the **day** and **month** time intervals you can choose relevant **display formats**:
| | |
| ------------- | --------------------------------------------- |
| Time interval | Display formats |
| Day | YYYY-MM-DD MM/DD/YYYY DD/MM/YYYY MMM DD, YYYY |
| Month | YYYY-MM MM/YYYY YYYY/MM MMM YYYY |
**Sort by**
Next, we have the **Sort by** dropdown, which will have the following options:
- **Categories // A-Z.** Order by the **Category** field values from A to Z.
- **Categories // Z-A.** Order by the **Category** field values from Z to A.
- **Values // A-Z.** Order by the **Value** field values from A to Z.
- **Values // Z-A.** Order by the **Value** field values from Z to A.
Example: If our **Group by** field is the Date field, and we select “**Categories //A-Z,”** we’ll have the following ordering: 2019-01, 2019-02, 2019-03, etc. (by alphabetical order), as on the screenshot above.
**Max categories**
**Include empty cells**
**Sub-grouping**
Lastly, we can choose to **Treat empty cells as 0** as well as **Show axis label**.
## Options
### **Orientation**
### Show zoom
### Show tooltip
When this option is enabled, the users will see a tooltip when hovering over each individual bar. The tooltip contains all the information about that specific bar.
### Enable download
When this option is enabled, the users will be able to download the chart to their device in **.svg** format.
## **Data sampling and data freshness**

_How much data a chart shows, and how fresh it is, in each mode._
### Charts in edit mode
- Data sampling - only a small sample of records is used to generate your charts in edit mode to optimize performance
- Data freshness - data shown in edit mode is real-time.
### Charts in preview mode
- Data sampling - all the specified records are being shown, limited by the max number of “records per dynamic block” specified in your plan.
- Data freshness - data refreshes every 15 minutes.
- Charts include the Information about when the data on the chart was last refreshed.
- App builders can instantly refresh data in preview mode. Instant data refresh is only available in preview mode for testing purposes. Not available to your end users in the live app.
### Charts in live mode
- Data sampling - all the specified records are being shown, limited by the max number of “records per dynamic block” specified in your plan.
- Data freshness - data refreshes every 15 minutes. Chartsinclude the Information about when the data on the chart was last refreshed.
### Hiding data freshness information
Sometimes, you might want to hide data freshness information, typically in cases where a chart serves purely as a visual aid for your narration on a website, rather than being the object of analysis.
Here’s a little custom CSS snippet that will allow you to hide the data freshness information:
```css
```
---
# Type: Bar Chart
Source: https://docs.softr.io/building-blocks/type-bar-chart
> **Note**
>
> Bar chart block is available for users on the [Professional plan and above](https://www.softr.io/pricing).

_Bar Chart_
This [chart](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/chart-block-overview/48LkSKXWY8TrBwjqBVXMqg) type lets you display your data through simple bars.
> **Info**
>
> Not sure how to setup charts? Learn more here → [Chart Block Overview](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/chart-block-overview/48LkSKXWY8TrBwjqBVXMqg).
---
# Type: Stacked Bar Chart
Source: https://docs.softr.io/building-blocks/type-stacked-bar-chart
> **Note**
>
> Stacked bar chart block is available for users on the [Professional plan and above](https://www.softr.io/pricing).
The Stacked Bar chart layout allows you to compare data in a part-to-whole manner, over time or across categories.
The setup is similar to that of a [Bar Chart](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/type-bar-chart/hs9Nn3rYv1PJFoJADwMWk6) with a unique feature: it allows the presentation of subcategories within a single bar (stacked), as opposed to showing each subcategory with a separate bar.
## Example
Let’s say you are a sales manager and you want to analyze bookings by month, split by deal owners. You want to both understand what is the total sum of won deals, as well as how each sales person (deal owner) contributed.
Here is the output chart we aim at preparing:

**Setting up the chart**
Take a look at the Airtable base example. It has different deals at different sales stages, close dates and deal owners.

_Airtable base with sales information_
Having a base, let’s add a Stacked Bar Chart block, and configure it.
**Conditional filters** – let’s take into account only the deals with a Deal stage: Won

**Aggregate function** – we want to SUM all the deal values

**Groupings**
Then we want to group these won deal values by the deal close date, with a month time interval →

Finally, we want to further group the data by deal owners →

The Stacked Bar Chart block is ready:

## Show and hide data point labels
Sometimes labels on stacked bars can look a bit too crowded, so among options shared with other chart types, the Stacked Bar Chart has an additional option to decide whether to show data point labels on stacked bars.

> **Info**
>
> Whether the label will be shown or not, a data point **tooltip** still shows up upon hovering over the bars.

_Show data point labels: ON_

_Show data point labels: OFF_
> **Info**
>
> Learn more about setting up charts → [Chart Block Overview](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/chart-block-overview/48LkSKXWY8TrBwjqBVXMqg).
---
# Type: Line Chart
Source: https://docs.softr.io/building-blocks/type-line-chart
> **Note**
>
> Line chart block is available for users on the [Professional plan and above](https://www.softr.io/pricing).

_Line Chart_
The **Line Chart** [chart](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/chart-block-overview/48LkSKXWY8TrBwjqBVXMqg) type represents the data through lines connected by nods.
> **Info**
>
> Not sure how to setup charts? Learn more here → [Chart Block Overview](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/chart-block-overview/48LkSKXWY8TrBwjqBVXMqg).
---
# Type: Area Chart
Source: https://docs.softr.io/building-blocks/type-area-chart
> **Note**
>
> Area chart block is available for users on the [Professional plan and above](https://www.softr.io/pricing).

_Area Chart_
The **Area Chart** is basically a [Line chart](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/type-line-chart/sr4V2LjKyhGdzbmAmEcwwy), where the area below the lines is color-filled.
> **Info**
>
> Not sure how to setup charts? Learn more here → [Chart Block Overview](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/chart-block-overview/48LkSKXWY8TrBwjqBVXMqg).
---
# Type: Scatter Chart
Source: https://docs.softr.io/building-blocks/type-scatter-chart
> **Note**
>
> Scatter chart block is available for users on the [Professional plan and above](https://www.softr.io/pricing).

_Scatter Chart_
The **Scatter** type is similar to the [Line Chart](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/type-line-chart/sr4V2LjKyhGdzbmAmEcwwy) with the only difference that there are no connecting lines between the nodes.
> **Info**
>
> Not sure how to setup charts? Learn more here → [Chart Block Overview](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/chart-block-overview/48LkSKXWY8TrBwjqBVXMqg).
---
# Type: Pie Chart
Source: https://docs.softr.io/building-blocks/type-pie-chart
> **Note**
>
> Pie chart block is available for users on the [Professional plan and above](https://www.softr.io/pricing).
**Pie Chart** is a circular graphic that is divided into slices to show numerical proportion. The setup of the **Pie Chart** block is similar to that of the **Bar Chart** described [here](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/chart-block-overview/48LkSKXWY8TrBwjqBVXMqg), but there are some differences related to the unique characteristics of this chart type, which we’re going to discuss here.
The following image illustrates a pie chart that uses the same the income/expense data from Airtable we used in our [chart block overview](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/chart-block-overview/48LkSKXWY8TrBwjqBVXMqg).

_Pie chart_
We’ve used the same **Sum aggregate function**, and we can see that each slice shows the sum of incomes and expenses for a given month, and what’s the proportion of each slice (e.g. 23.81% for January). At the top of the chart, there’s the **Legend** section, which indicates which color corresponds to which record or group of records. So, let’s see how the Legend is configured.
## Chart legend
First of all, you can choose whether you want to display a Legend or not. If the toggle is enabled, you can change the **Legend position** as well as switch the **Legend direction** between **vertical** and **horizontal** options.

_Legend settings_
> **Info**
>
> Not sure how to setup charts? Learn more here → [Chart Block Overview](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/chart-block-overview/48LkSKXWY8TrBwjqBVXMqg).
---
# Type: Donut Chart
Source: https://docs.softr.io/building-blocks/type-donut-chart
> **Note**
>
> Donut chart block is available for users on the [Professional plan and above](https://www.softr.io/pricing).

_Donut Chart_
The Donut Chart is a [Pie Chart](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/type-pie-chart/wqQRQCAV5nf6jGvbJnNsGV) with its center cut out to look like a donut.
> **Info**
>
> Not sure how to setup charts? Learn more here → [Chart Block Overview](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/chart-block-overview/48LkSKXWY8TrBwjqBVXMqg).
---
# Type: Rose Chart
Source: https://docs.softr.io/building-blocks/type-rose-chart
> **Note**
>
> Rose chart block is available for users on the [Professional plan and above](https://www.softr.io/pricing).

_Rose Chart_
The **Rose Chart** is a radial graph with multiple axes radiating out from the centre. Instead of points being plotted along an axis, bars are drawn to show the quantity of each variable. **Rose Charts** are commonly used to indicate wind speed or noise levels.
The setup of the block is similar to that of the [Pie Chart](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/type-pie-chart/wqQRQCAV5nf6jGvbJnNsGV).
> **Info**
>
> Not sure how to setup charts? Learn more here → [Chart Block Overview](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/chart-block-overview/48LkSKXWY8TrBwjqBVXMqg).
---
# Summary Cards
Source: https://docs.softr.io/building-blocks/summary-cards
> **Tip**
>
> The Summary Cards block is a legacy block and is no longer available for use in new apps. It has been deprecated as of September 9, 2025. The block will continue to function inside any existing applications where it is being used.
This block is for displaying data from a [data source](/4230abecf813402aa2926466c313290a) in a specific format that's suitable for summaries, key stats, and similar. So, let's go through the block settings and see how it works.
## Conditional Filters
You can learn more about conditional filters [here](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU).
## Summary Options
In this section, you can customize the **Title** and **Subtitle** of the block.
## Summary Card
This is where you customize the layout of the summary card and map the fields from your [data source](/4230abecf813402aa2926466c313290a). So, let's see how this works on a practical example. Let's say you have an [Airtable](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX) table with quarterly revenue data for a number of companies, and you want to summarize the annual revenue of each company on your Softr app. Below you can see our table, where we have added a **Sum** formula field that calculates the annual revenue based on data from each quarter. We also have the **names** of the companies and a **Color** field, which we are going to use to apply different colors to each summary card.

_Revenue data on Airtable_
> **Tip**
>
> For the **Color** field, the values need to be specified either as text (e.g. "Red") or as the HEX equivalent of the preferred color (e.g. "#FF00000"). In Airtable, you can use any text field type (e.g. Single Select or Single line text).
>
> If you don't connect a Color field, the cards will be assigned random colors.
Finally, let's connect the data to our Summary block and set it up.

_Setting up the block_
---
# Column Container
Source: https://docs.softr.io/building-blocks/column-container
## Overview
This Block Container lets you arrange blocks side by side in columns, creating flexible and visually appealing layouts. It's ideal for dashboards, account details, and other structured content, helping you organize related information more effectively within a single container.
### 1. How to add a block container
You can find Block containers in the Block Panel and add it to any page on your application.

### 2. Select layout
You can choose from several predefined column layouts within the Block Container. These options include:

- **Two Columns**
- **Three Columns**
- **Four Columns**
- **1:2 Layout** (one-third width and two-thirds width)
- **2:1 Layout** (two-thirds width and one-third width)
- **1:3 Layout** (one-fourth width and three-fourths width)
- **3:1 Layout** (three-fourths width and one-fourth width)
- **1:2:1 Layout** (one-third, one-third, one-third)
> **Note**
>
> You can easily switch between these layouts after selecting one.
### 3. Add blocks to the container
After selecting a layout, you can add blocks to the individual container's columns. Not all block types are available for use in these layouts.

Currently supported blocks include:
- **Charts**
- **Summary Cards**
- **List** (New)
- **Grid** (New)
- **Item Detail** (New)
- **Comments**
- **Maps**
- **Static Blocks** (Simple Image, Simple Text, CTA)
> **Note**
>
> Form, Calendar, and Table blocks will be supported in future updates.
### 4. Customize block container
You can customize the appearance and behavior of the Column Block Container with the following options:
- **Title and Subtitle:** Set a title and subtitle for the container.
- **Layout**: Change column layout
- **Block Alignment:** Adjust the alignment of blocks within the container.
- **Background Color:** Choose a custom background color for the container.
- **Padding:** Adjust padding around the blocks within the container.
- **Border Style:** Customize the border style of the container.
- **Visibility:** Set visibility options for the container.
> **Warning**
>
> Please note that visibility settings apply to all blocks within the container; individual block visibility is not supported.

### 5. Move blocks in/out of the container
Easily move blocks in or out of the container using an action button on the canvas without losing your existing settings.
> **Warning**
>
> Only supported blocks of the latest versions can be moved into the container.

---
# Tabs
Source: https://docs.softr.io/building-blocks/tabs
## **Overview**
The **Tabs Block Container** helps you organize your content into horizontal tabs on a single page. Instead of stacking everything into one long, scroll-heavy layout, you can split related content into neat, clickable tabs. This makes it easier for users to navigate and quickly find the information they need.
## **How to Use the Tabs Block Container**
### **1. Add the Tabs Container**
To add the Tabs Block Container to your page:
1. Click **Add Block** in the page editor to open the block panel.
2. Go to the **Containers** section.
3. Select **Tabs** from the available block options.
4. A new tab container will appear on your page. Each tab will serve as its section for content.
5. You can add as many tabs as needed by adjusting the settings panel.

_Adding a tab container_
### **2. Add Blocks to Tabs**
Once you’ve added tabs:
1. Open a tab by clicking on it in the settings panel or directly on the canvas.
2. Click the **Add Block** button on the canvas to insert content into each tab.
3. You can add any block to each tab, making it easy to organize your content.

_Adding blocks to tabs_
Each tab can hold different types of information, keeping things organized and easy to navigate. Here’s how you might use them:
- **Content Organization:** Group large content sections into separate, manageable tabs for easier access.
- **Data Display:** Use tabs to show different views of the same data (e.g., filtered datasets or reports).
- **Record Details:** Organize complex records, like customer information, by grouping related fields into individual tabs.
### **3. Customize Your Tabs**
You can customize both the appearance and behavior of your tabs using the settings options:
**Tab Settings:**
- **Rename a Tab:** Click on the tab label to rename it. Name your tabs based on their content (e.g., "Overview," "Details," "Reports").
- **Add Icons:** Customize your tabs by adding icons next to each label.
- **Reorder Tabs:** Drag and drop tabs to rearrange them in the desired order.
- **Show Title and Subtitle:** To provide context for the content inside, set a title and subtitle for the entire tab container.

_Customizing tabs_
**Tab Style Settings:**
- **Tab Container Style:** Adjust the background color and padding of the entire Tabs Block Container.
- **Customize Tab Labels:** You can modify the size, font of your tabs.
- **Title & Subtitle Customization:** Style the tab container's title and subtitle to match your page's design.
### **4. Set Visibility Rules**
You can control who sees your tabs by using visibility rules, allowing you to tailor content access to specific user groups:
**Visibility for the Entire Tab Block:**
1. Select the **Tab Container** in the editor.
2. Click on **Visibility** and define the rules. This will control access to the entire tab block, including all tabs and their content.
**Visibility for Individual Tabs:**
1. Open the **Tab Settings**.
2. Click on **Tab Visibility** and define rules for specific tabs. This allows certain tabs to be visible to select users while hiding others.
**Visibility for Blocks Inside Tabs:**
1. Select a block within a tab.
2. Go to **Visibility Settings** and define rules for the block. This will restrict access to certain blocks within a tab for different user groups.
### **5. Move Blocks In/Out of Tabs**
You can easily move blocks in or out of the tab container without losing any of your existing settings:
1. Hover over the block you want to move.
2. Click on the **Move to Container** button.
3. Select the **Tabs Container** and choose the tab you want to move the block into.
4. Similarly, once the block is inside the tab, click the canvas Move out button to move it outside the tab container.

_Moving block inside a tab_
---
# Account Settings
Source: https://docs.softr.io/building-blocks/account-settings
## Overview
The Account Settings block lives on the Account Settings page in your app and allows your users to self-manage their email, password, name, photo, and any other fields you want to let them edit. You can turn on this page by adjusting your settings in [User Authentication](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/user-authentication/7gJmq6B7syYE3hRoFxLs5J). Read more about Utility pages [here](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/utility-pages/49UoDpTpTPbkoKVwksoqfh).
To edit the Account Settings page and block, click on the Pages menu button, scroll to the Utility pages section, and select the Account Settings page. Once on the page, click anywhere on the page to bring up the block settings.

## Content
The content tab holds a variety of options for you to adjust the Account Settings block:
### **Cover Image**
The Cover Image can be toggled off or on and you can upload a custom cover image to suit the look and feel of your app.

### **Title and Subtitle**
The Title and Subtitle are shown at the top of the page and can be changed to whatever you like or removed completely if needed.

### **Form Fields**
The Form Fields section offers a ton of functionality for controlling what users can edit about their account or profile. The fields above the divider are defaults and cannot be turned off, because they provide critical functionality your app needs to function. However, they do offer several options to customize how they look and function:
- **Avatar**: This field can be disabled completely if no avatar is desired or available for users.
- **Email**: This field can be customized with custom text for everything from the field name itself to allowing users to change their email addresses and the messaging around it. To edit the password reset emails themselves, check out [User Email Notifications](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/user-email-notifications/sZRpewgUkBFFvhKSsQrBx7).

- **Password**: Change the language and labels of the password editing/reset capabilities. Note that users using SSO or Google Sign-in will not be able to change their password here.
- **Name**: Change the placeholder text and control if you want to let users update their name or not.
You can also add custom fields that you want users to be able to change about their profile by clicking on the **Add Field** button. Customize the field type, label, and placeholder like you can on forms, list blocks, or anywhere else in Softr.

### Update Button
Edit the text on the Update button to suit your language or preferred phrasing. Also update the success message to display to the user once the change is confirmed.
## Styles
Click on the Styles tab to change everything from background color, sizing, and rounding to surface/card colors and shadows. Other elements like text color and button color can be changed in your app’s [Theme panel](/styling/7qXYEkNvWQamR6vcLXzZnF/application-theme/91YGSL2aDJajXdbPBhitbc).

---
# Signup
Source: https://docs.softr.io/building-blocks/signup
## Overview
The Signup utility page and included block allow users to signup to your app directly, with some special options for who should sign up and how. The availability of this page is determined by your [User Authentication](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/user-authentication/7gJmq6B7syYE3hRoFxLs5J#sign-up) settings.
You can also create multiple signup pages by duplicating the original Signup page. This is helpful for use cases where you may need to use Hidden fields to automatically assign user groups to users who signup from various locations or for different purposes and roles.
To access the Signup page:
1. Ensure Login and Signup is enabled in [User Authentication](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/user-authentication/7gJmq6B7syYE3hRoFxLs5J#sign-up)
2. Click on the Pages menu
3. Select the Signup page from the Utility pages section
4. Click anywhere on the signup page itself to open additional settings.

## Content
Click on the Content tab to open up settings about how the block needs to function.
### Logo
This section allows you to turn logo display off and on, choose square or horizontal version of your logo and also control the position of it on the signup form.

### Title and Subtitle
The Title and Subtitle are shown at the top of the signup form and can be changed to whatever you like or removed completely if needed.

### Hidden Fields
Hidden fields allow you to automatically pass information as a part of the signup without requiring the user to input anything. This is especially helpful for use cases like:
- Automatically assigning a status or role to a user that signs up
- Saving UTM parameters from the URL bar
- Saving custom tracking codes, invite codes, or affiliate codes from parameters from the URL bar
- Automatically assigning a user to company by using separate sign-up pages for each company
You can add a hidden field to the form just like anywhere else in Softr. First, ensure you are [syncing your users with a datasource](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/syncing-users-with-a-data-source/hshRGygHr4T33EnaLntGf9). Click **Add Field**, then choose the field from your user-synced data source that you want to save as a part of signup. You won’t be able to change the field type, however visible fields will be available in the future.

### Authentication Flows
Authentication flows are the methods that you want to allow your users to signup with. These are determined, again, by your User Authentication settings, but they can be hidden on any Signup page by clicking the **Eye** icon.. This is helpful for providing a signup page for a company requiring only SSO signup, while also providing a public page for only Google Sign-in, for example.

### Side Section
The Side Section allows you to change the background image and its position, heading and sub-heading and featured image or disable it completely. When disabled, the Signup form will be centered on the page. Edit and rearrange the heading, subheading, and feature image to suit your needs and brand.

### Consent Message
The Consent Message can be customized to house links to your terms, privacy policy or display any other text that the user may need to know before signing up to your app. It features a basic rich text editor for bolding, italicizing, underlining, striking, or placing hyperlinks. You can also disable this text completely if needed.

### Redirect to Login
Here you can customize the text shown to users to help redirect them to the login page if they already have an account. While you can change the text “Log in”, it will always send the users to the Log in page regardless of what you put in the blank.

### Validation Message
The validation message area allows you to customize the text that is show to the user if:
- The email they are trying to signup with is already in use.
- The email they are trying to signup with is not whitelisted by the “Domain-restricted signup” domains in the User Authentication.

### Recaptcha
Recaptcha is a service provided by Google that allows you to check the validity of the user signing up. It checks to ensure the user is a human and not a robotic web-crawler. Turning this on will require the users to complete a small verification task. Additional setup is required outside of simply toggling this on, so be sure to follow the [Recaptcha guide](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/advanced-form-features/jCim5VWZePgZuaRsUZBnpG#enable-recaptcha).
## Styles
Click on the Styles tab to change everything from background color, sizing, and rounding to surface/card colors and shadows. Other elements like text color and button color can be changed in your app’s [Theme panel](/styling/7qXYEkNvWQamR6vcLXzZnF/application-theme/91YGSL2aDJajXdbPBhitbc).

---
# Onboarding Flow
Source: https://docs.softr.io/building-blocks/onboarding-flow
Softr's **Onboarding Flow pages** let you deliver a polished, customized onboarding experience the first time a user logs in—whether they're signing up or being invited to your app.
Use it to prompt users to complete their profile, create a new record (e.g. a company connected to that user), or simply guide them through the app—all without custom code or workarounds.
## ✨ What you can do with onboarding flows
- **Welcome new users with a tailored experience**
Capture key profile info, add a linked record, or display a welcome message or walkthrough.
- **Show different flows to different users**
Assign onboarding flows based on **signup page** or **user group**—so team members, clients, or partners get the right experience.
- **Track onboarding progress at a glance**
See onboarding status directly in the **Users** tab, and manually mark as completed or reset if needed.
---
## 🔧 How to set it up
### 1. Add an onboarding flow page
- Go to **Pages** in the left-side menu
- Under **Utility Pages**, click **Onboarding Flow**
You can create as many onboarding flows as needed—each one will be treated as its own dedicated utility page. Every app must have at least one onboarding flow.

---
### 2. Choose your flow type and data setup
- In the **Settings** tab of the onboarding page, choose your **Flow type**:
- **Complete user profile** – collect additional profile fields related to the user (e.g. role, preferences). Note that this will only be possible if you have your [Users synced with a data source](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/syncing-users-with-a-data-source/hshRGygHr4T33EnaLntGf9).
- **Add new record** – capture a linked record like a form response or onboarding survey
- **Display information only** – show static content like welcome instructions or next steps
- Link to the relevant **data source** and **table** (if applicable)

---
### 3. Set the steps
- Navigate to the **Steps** tab
- Define the content or inputs users will go through. This is the same form builder as conditional forms, but it's specifically used to build the steps they should go through in the flow.
- Choose what happens when onboarding is complete (e.g. redirect to dashboard, thank-you page, or other app page)

---
### 4. Assign who sees each onboarding flow
- Go to either the **Assign** button in the **Settings** tab, or go to **Pages > Page Rules**.
- Assign your onboarding flow to specific users based on either:
- **Signup Page, or**
- **User Group**
> **Tip**
>
> The onboarding flow will only appear during a user's **first login session** based on these rules.

---

### 5. Create additional flows
- Need different onboarding flows for different users?
Just **duplicate your existing Onboarding Flow utility page**, update the content, and apply new rules.
---
### 6. Track and manage onboarding status
- Go to the **Users** tab > User table
- Scroll to the **Onboarding** column to see each user's onboarding status
- You can also manually:
- **Reset onboarding** for a user
- **Mark onboarding as completed** if needed

---
## ✅ Things to keep in mind
- Onboarding flows are **only shown once**, on the user's first signup/login
- You can set up **multiple flows per app** and control visibility with [Page Rules](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/page-rules/6zZKpehWhQhCGH9XXAFrpT).
- All onboarding flows live under [**Utility Pages**](https://docs.softr.io/application-settings/n3K2UEfpC9BpHgakMzUU5Y/utility-pages/49UoDpTpTPbkoKVwksoqfh), and can be managed like any other Utility page
---
# Link Expired
Source: https://docs.softr.io/building-blocks/link-expired
## Overview
When you use Magic Links for user authentication or send invitation links for users to join your app, they will be using a unique link. Invite links expire after not being accepted within a certain timeframe. With Magic Links, although they never expire, they can be re-generated or deleted altogether in the Users menu. In either of the cases where the links are no longer valid, users will be sent to the Link Expired page in your app.
You can name this page whatever you like, but the functionality will remain the same. The Link Expired page will only appear if Login is enabled in the [User Authentication](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/user-authentication/7gJmq6B7syYE3hRoFxLs5J) settings.
To access the Link Expired page/block:
1. Ensure Login is enabled in the [User Authentication](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/user-authentication/7gJmq6B7syYE3hRoFxLs5J) settings.
2. Click on the Pages menu
3. Select the Link Expired page from the Utility pages section
4. Click anywhere on the block itself to open additional settings.
## Content
Click on the Content tab to change how the block should function, the image/icon, and the text that should be displayed to the user. You can also turn the button off/on and change where the button should send the user.

## Styles
Clicking on the Styles tab will open up panels for changing the page background color, the font colors and sizes, and the button styles.

---
# Permission Denied (401)
Source: https://docs.softr.io/building-blocks/permission-denied-401
## Overview
A 401 page is an error message shown by a web server when a user tries to access a resource without proper authentication. It indicates that the request lacks valid credentials, such as a username or password, and prompts the user to log in or provide authorization.
In Softr we call this page Permission Denied, but you can change this to whatever you like - the functionality will stay the same. The page cannot be deleted or removed except by disabling Login functionality in your app’s [User Authentication](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/user-authentication/7gJmq6B7syYE3hRoFxLs5J) settings.
To access the Permission Denied page/block:
1. Ensure Login is enabled in the [User Authentication](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/user-authentication/7gJmq6B7syYE3hRoFxLs5J) settings.
2. Click on the Pages menu
3. Select the Permission Denied page from the Utility pages section
4. Click anywhere on the block itself to open additional settings.

## Content
Click on the Content tab to change how the block should function, the image/icon, and the text that should be displayed to the user. You can also turn the button off/on and change where the button should send the user.

## Styles
Clicking on the Styles tab will open up panels for changing the page background color, the font colors and sizes, and the button styles.

---
# Page Not Found (404)
Source: https://docs.softr.io/building-blocks/page-not-found-404
## Overview
A 404 page is a standard error message displayed by a web server when a requested webpage cannot be found. It typically appears when a user tries to access a page that has been moved, deleted, or mistyped, informing them that the resource is unavailable.
In Softr, by default we call this page “Page Not Found”, but you can change it to whatever you like. This page cannot be turned off or deleted as it provides critical navigational functionality that every website and app needs. Typically 404 pages are not indexed by search enginers.
Many companies choose to make this a fun, cheeky page to help guide users back to known website pages. To access the Page Not Found (404) page and utility block:
1. Click on the Pages menu
2. Select the Page Not Found page from the Utility pages section
3. Click anywhere on the block itself to open additional settings.

## Content
Click on the Content tab to change how the block should function, the image/icon, and the text that should be displayed to the user. You can also turn the button off/on and change where the button should send the user.

## Styles
Clicking on the Styles tab will open up panels for changing the page background color, the font colors and sizes, and the button styles.

---
# Calendar
Source: https://docs.softr.io/building-blocks/calendar
The **Calendar Block** provides a dynamic way to display and manage date-based information. Perfect for organizing schedules, tracking deadlines, or visualizing project timelines, it helps users see upcoming events and tasks at a glance.

## **Use case examples**
- **Project Timelines:** Map out project milestones, deadlines, and task timelines.
- **Company Calendar:** Coordinate team schedules by visualizing meeting times, vacation days, and work shifts in a single shared calendar. Use color coding to distinguish between team members or event types.
- **Training Sessions:** Schedule employee training events and allow easy access to session times, locations, and participant lists.
> **Note**
>
> Calendar block is available for Professional, Business, and Enterprise plans.
# Configure a Calendar block
> **Tip**
>
> **Build with AI:** Instead of configuring manually, you can add a Calendar block instantly with the **AI Co-Builder**. Just click the AI icon in the editor and type: _"Add a calendar showing our upcoming marketing campaigns."_
## Source
The **Source** panel connects the list block to your data source. Here, you can:
- Connect the list block to your[data source](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/connect-your-data-source/41p6U2eZs6NZ5qZp7iKvnn).
- Set up[conditional filters](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/conditional-filters/mDnn7jnpPiYmJcT99jpt7m) to display only the data that meets specific criteria.
- **Define sorting rules** and set the number of items to display per page.
- **Customize the empty state message** that appears when no data matches the requirements.
Once you connect to your source data, you can configure Content, Actions, and block Visibility settings.
> **Info**
>
> Some configuration options depend on the [data source](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/connect-your-data-source/41p6U2eZs6NZ5qZp7iKvnn). For more details, check the documentation for your specific data source.

## **Content**
In the **Content** tab, customize the Calendar layout data fields, adjust their display, and add features like search and filters to help users find information quickly.

_The Content tab of the Calendar block._
### **Event fields**
The **Calendar block** uses default event fields to display your events. Make sure to map the following required fields:
- **Event Title:** Displays the name of the event on the calendar.
- **Start Time:** Specifies when the event begins, shown on the calendar.
- **End Time:** Specifies when the event ends, shown on the calendar.

> **Info**
>
> If you’re using [GSheet](/data-sources/1YYStCJukT15Lh2j93qo9A/google-sheets/jznC9Jr3Jri224AVmHVn4a) as your data source you can specify if the date field includes time and define the time format you would like it to be displayed.
### Calendar Views
Customize how users interact with the calendar by enabling multiple view options. Available views include:
- **Month View:** Ideal for an overview of all events within a month.
- **Week View:** Focuses on events for a single week, with detailed time slots.
- **Day View:** Displays events for a single day, perfect for detailed scheduling.
- **Agenda View:** Lists events in chronological order for a streamlined overview.
You can decide which views are available for your users and set a **default view** they will see when they open the calendar.

### **Event Popover**
The **Event Popover** appears when a user clicks on an event. By default, it includes:
- Event Title
- Event start and end date
You can customize the popover to include additional fields from your data source, such as location, description, or tags, providing more context for each event.

### **Item fields**
**Item Fields** lets you connect fields from your **data source** to each list item, making it easy to display the information you need. You can control what information appears by adding, removing, or rearranging fields such as task names, assignees, or descriptions.
For each field in the **Item Fields** section of the secondary section, you can customize the following options:
- **Type:** Defines the display field type that controls how content appears in the block (e.g., text, checkbox, or image).
- **Content:** Chooses the specific data field from connected data sources to display.
- **Label (Optional):** Adds context to the field. If left blank, the label will not be visible to users.

> **Info**
>
> **Note:** Some display field types are compatible only with specific data formats. For example, if a field is set to display images, you cannot map it to text data. Ensure the field type matches your data source field format to avoid display issues.
**Supported field types**
| | |
| ----------------- | --------------------------------------------------------------------------------------------------------- |
| **Display Field** | **Description** |
| **Text** | Displays plain text. Ideal for names, titles, or short descriptions. |
| **Rich Text** | Supports long text, markdown, or HTML formatting. Allows for more detailed descriptions or notes. |
| **Headings** | Various heading sizes. |
| **Email** | Displays email addresses as clickable mailto links, allowing users to start an email directly. |
| **URL** | Displays website links as clickable URLs, allowing users to navigate to external pages. |
| **Tag** | Allows you to display one or more tags, helpful for organizing items by category or status. |
| **File** | Provides a link for users to download attachments, such as PDFs or other documents. |
| **Video** | Embed video content from a supported source, allowing users to watch content directly in the block. |
| **Audio** | Embed audio files, letting users listen to content directly within the block. |
| **Image** | Displays a single image, useful for things like profile pictures or product images. |
| **Image gallery** | Displays multiple images in a gallery format, useful for showcasing a collection of visuals. |
| **Embed** | Allows you to embed content from other services, such as YouTube videos, Calendly, or social media posts. |
| **Rating** | Displays a rating system, typically with stars, to visually represent ratings or scores. |
| **Checkbox** | Shows a checkbox, useful for indicating completed items or allowing users to mark items as done. |
| **Divider** | Visual content separator. |
### **Search bar**
The **Search Bar** allows users to search through items in your block, making it easier to find specific entries quickly.
You can configure which parameters you want the search to be performed by adding fields to Search by input. For instance, if you’re displaying a list of employees, you might select “Name,” “Department,” and “Job title” as searchable fields.

> **Info**
>
> If no fields are selected, the search bar will display all items regardless of the search term. To ensure meaningful search results, always select at least one field.
## Actions
[Actions](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/actions-adding-and-editing-data-/41p6U2eZs87asLz6dV5AMy) let you define what happens when users interact with a block, such as navigating to a new page, editing records, or triggering workflows. This ensures your app not only displays data but also offers dynamic user engagement.

**Topbar buttons**
- [Add record](/actions/ntEfT9zSJk6aY54G6W5KGU/add-record/3LrUMpQY4BKfDDQj6eb8h8): Create new entries in your data.
- [Open page](/actions/ntEfT9zSJk6aY54G6W5KGU/item-on-click-actions/f1ns7phZfNNvgwXA6tTN3M): Navigate to another page within your app.
- **Open URL**: Redirect users to an external link.
- **Scroll to**: Move the view to a specific section within the block.
**On Click Actions:**
- **Do nothing:** Nothing happens when the user clicks on the item.
- **Open popover:** Opens the default popover
- **Open URL**: Redirect users to an external link.
- **Scroll to**: Move the view to a specific section within the block.
- [Open details page](/actions/ntEfT9zSJk6aY54G6W5KGU/item-on-click-actions/f1ns7phZfNNvgwXA6tTN3M):: Open the details page of the selected record.
**Event popover buttons:**
- [Edit record](/actions/ntEfT9zSJk6aY54G6W5KGU/edit-record/irSJXPF1gCMXNmfsQFscvx): Modify the details of a specific record.
- [One-Click Update](/actions/ntEfT9zSJk6aY54G6W5KGU/one-click-update/8BaX5i6KLZhZCrSZERGnej): Apply predefined updates to a record with a single click.
- [Open details page](/actions/ntEfT9zSJk6aY54G6W5KGU/item-on-click-actions/f1ns7phZfNNvgwXA6tTN3M): Open the details page of the selected record.
- [Delete Record](/actions/ntEfT9zSJk6aY54G6W5KGU/delete-record/peV9LGdJbM9sKHKynqopkH): Remove a record from your data.
- **Open URL**: Redirect users to an external link.
- **Scroll to**: Move the view to a specific section within the block.
- [Download file](/actions/ntEfT9zSJk6aY54G6W5KGU/download-file/8Sr2y4CREVcW2GEEDYUhfJ): Provide users with a direct option to download associated files.
- [Call API](/actions/ntEfT9zSJk6aY54G6W5KGU/call-api/i9f1s3w9wib3oRmS4HZ7MX): This action triggers a custom API call for advanced integrations (_available for Professional, Business, and Enterprise plans)._
## Visibility
Control who can see a block by setting up [visibility](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/block-visibility/3spA2dfQNrcGcPNmnDXHB3) rules. This helps tailor the user experience by showing relevant content to the right audience, improving personalization and security.

## Style
Customize the look and feel of your blocks with s[tyling](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/style-your-app/41p6U2eZs8AZmBW8mHykXA) options. Adjust fonts, colors, spacing, and more to align with your app’s branding and create a polished, professional design.

## Relevant Guides
- [How to set up a record detail page?](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/item-details-block-/4bE8XaFbJp45wkAwuWiz8f)
- [How to filter list records by Page URL parameter?](/how-to-guides/ioi5BbuQ2RDM7aHPrpXnjG/how-to-filter-list-by-page-url-parameters/42JZoeYwMstwaL9aoBdRjz)
---
# Kanban
Source: https://docs.softr.io/building-blocks/kanban
> **Note**
>
> Kanban block is available for users on the [Professional plan and above](https://www.softr.io/pricing).

_A Kanban board of tasks in a Softr app._
The Kanban block shows records from a [data source](/4230abecf813402aa2926466c313290a) as cards in columns, like a [Kanban board](https://en.wikipedia.org/wiki/Kanban_board). Each column is one value of a field, such as a status.
This page uses a table in [Softr Databases](/softr-databases/softr-databases-overview). Connecting the data source, inline filters, and search work like they do in the [List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU) block. So this page covers the settings that are specific to the Kanban block.
> **Tip**
>
> You can let users **Drag and Drop** items, [Add Records](/actions/ntEfT9zSJk6aY54G6W5KGU/add-record/3LrUMpQY4BKfDDQj6eb8h8), [Edit Records](/actions/ntEfT9zSJk6aY54G6W5KGU/edit-record/irSJXPF1gCMXNmfsQFscvx), and more in the **Actions** tab of block settings through [Action Buttons](/actions/ntEfT9zSJk6aY54G6W5KGU/action-buttons-overview/idg8Fqf2kjFwcx6kyP3jNq).
> **Tip**
>
> **Build with AI:** Instead of configuring manually, you can add a Kanban block instantly with the **AI Co-Builder**. Just click the AI icon in the editor and type: _"Create a Kanban board of my tasks grouped by their priority."_
## Prepare your data
To show how the block works, we'll use a **Tasks** table in a Softr Databases database. It has five fields:
- **Task** (Short Text)
- **Details** (Long Text)
- **Status** (Select) with the options To do, In progress, In review, and Done
- **Priority** (Select) with the options High, Medium, and Low
- **Assignee email** (Email)

_The Tasks table in Softr Databases._
Learn more about the available [field types](/softr-databases/field-types).
## Connect the block to your table
1. Add a Kanban block to your page.
2. Open the **Source** tab of the block settings.
3. Select **Softr Databases** as the account.
4. Select the database, then select the table.

_The Source tab: the account, the database, and the table._
## Group by
Open the **Content** tab. Under **Group by**, select the field that sets the columns. In our example, we select **Status**.
The board gets one column for each option of the field: To do, In progress, In review, and Done. Each card sits in the column that matches its value.

_The Content tab: the title of the board, Group by, and the columns._
By default, **Show all available options** is on, so every option of the field becomes a column. Turn it off to choose the columns yourself.
## Choose what shows on each card
Under **Item fields**, map the fields that appear on the cards. In our example, **Task** is the heading, **Details** is the text, and **Priority** is a tag.
The footer shows two short fields side by side, such as a tag or a date.
Under **Column options**, choose the style of the board (Standard, Minimal, or Joined), the column width, and the height. You can also show the card count and hide overflowing columns.

_Item fields and column options._
## Show each user only their tasks
Kanban's conditional filters work like those of the [List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU) block. They are in the **Source** tab, under **Record filters**.
For our example, each logged-in user should see only their own tasks. To do that, add a condition: **Assignee email** is the logged-in user's email.
1. Under **Record filters**, click **Add condition**.
2. Select the **Assignee email** field.
3. Select **Is**.
4. Select the logged-in user's email as the value.

_A record filter: Assignee email is the logged-in user's email._
Here is what **** sees after logging in and opening the board.

_The board of one logged-in user._
## Move cards between columns
If the **Drag and drop** toggle is on under **Actions**, logged-in users can drag cards between columns. You can also let only specific user groups move cards, through the [visibility settings](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/action-button-visibility/tqpb8TkUD4U4DCAUA2hjKo) of the toggle.

_Dragging a card from In progress to In review\._
When a user moves a card to another column, the value of the card changes in the table too. In our example, we move **Design onboarding checklist** from **In progress** to **In review**. In Softr Databases, its **Status** changes to **In review**.

_Before the move, the Status of the task is In progress._

_After the move, the Status of the task is In review\._
---
# Organizational Chart
Source: https://docs.softr.io/building-blocks/organizational-chart
> **Note**
>
> Organizational chart block is available for users on the [Business plan and above](https://www.softr.io/pricing).
The Organizational Chart block is used to represent a hierarchical relationship between a group of items. The most common use case is mapping relationships between organization employees to present the whole organization hierarchy visually. So, let's see how the block is configured.
## Linking to a data source
The data for the chart is fetched from a [data source](/4230abecf813402aa2926466c313290a), so, first of all, we need to link the data source where our Organizational Chart data is located. This works the same way as for the [Bar Chart](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/type-bar-chart/hs9Nn3rYv1PJFoJADwMWk6). However, prior to connecting the data source, we need to have our data ready to be mapped to. In the next section, we'll show you how to set up the data with organization employees that can later be connected to our Org Chart block.
## Setting up the data source
You can use Airtable or Google Sheets for the datasource - the setup is the same. For Google Sheets, ensure you have the first row setup as the column names. For linked fields, you’ll need to use the Softr-generated record ID to link records together. For more information using Linked Record fields in Google Sheets, please refer to the [Google Sheets](/data-sources/1YYStCJukT15Lh2j93qo9A/google-sheets/jznC9Jr3Jri224AVmHVn4a) help document.
We’re going to demonstrate the process using [Airtable](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX) data. Below, you can see the table we've set up for our chart. It's a simple list of organization employees with such fields as **Email, Name, Position, Profpic, Department, Supervisor**. The **Supervisor** field is a really important one, as it's used to establish the relationships between the employees. Therefore, let's examine it in greater detail.

_Org Chart Data on Airtable_
### Establishing relationships between employees
As mentioned above, the Supervisor (can be called anything) field is where you establish the hierarchical relationships between the chart nodes (organization employees in our case). It's a **Parent** relationship, so for each employee you need to select the person he/she **reports to**.
> **Tip**
>
> The Supervisor field needs to be a [Linked Record](https://support.airtable.com/hc/en-us/articles/206452848-How-to-link-records-in-Airtable) that's linked to the **same table**, so that you are able to map your employees to other employee records in the same table.
Below, you can observe the process of creating the Linked Record and selecting the Parent records.

_Configuring the Supervisor Linked Record field_
> **Tip**
>
> As, you can see, we've disabled the **Allow linking to multiple records** option since the Organizational Chart block doesn't allow to define a parent relationship to more than one record.
>
> Moreover, we've left Supervisor field **empty** for the company CEO (**top node**), as this record is not reporting to anybody and is going to be at the top of the chart.
Now that our Airtable data is ready, let's proceed to mapping the fields from our chart block.
If you’re using **Google Sheets**, you can use a VLOOKUP formula to pull in the Softr ID of an employee’s manager who is stored in the same sheet. This allows the Organizational chart in Softr to lookup the user record of the employees manager and show the heirarchy appropriately. Note that this is a computed field, and is determined by the name in the Manager column.

## Mapping the chart fields
In the **Features** tab of block settings we first have the **Title** and **Subtitle** fields, which are used to add headings to the block.
Further on, there are 5 fields that we are going to map to the Airtable table we set up previously. Below you can see how that's done.

_Mapping the chart fields_
That's it. You can now publish your Softr app and present your team in a nice org chart layout.
---
# Map
Source: https://docs.softr.io/building-blocks/map
The **Map** block can be used to display a list of locations from a [data source](/4230abecf813402aa2926466c313290a) through a **Google Map**. Let's see how it's configured.
> **Tip**
>
> Maps block is available on **all paid plans**.
## Preparing Data
First of all, you need to have the list of your locations in your data source. Let’s use [Airtable](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX) as an examples and set up the data there. Below you can see the example data set we're going to use.

_Map data_
As you can see, we've added three cities with their respective **coordinates**, **images**, and **URLs**. The **Image** and **URL** fields are optional and, if added, will be displayed inside the pop-up that opens when clicking on the location. We'll discuss this in greater detail a bit later.
## Setting up the map block
As soon as we have our data, we can proceed to setting up the Map on Softr. So, let's add the block and start configuring it.
### **Selecting Base and Table**
First of all, we need to select the **base** and **table** where the map data is stored. To do that, we need to navigate to the **Data** tab in block settings.

_Connecting Base and Table_
### **Inline Filters**
Now, let's navigate to the **Features** tab and see what we got there. **Inline Filters** let you add a filter to your Map to allow users filter the map by a given field. This works similar to the [List block inline filters](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU).
### **Map Options**
**Title and Subtitle**
Here, you can add a Title and Subtitle for the block.
**Map API Key**
To be able to use the map, you need to create an API key through your Google developer account and add it in **Settings => Integrations => Google Map**. A detailed guide on setting up the API key can be found [here](https://developers.google.com/maps/documentation/javascript/get-api-key).

_Adding Google Map key_
**Zoom**
Here, you define the zoom level of the map. The map can have a different number of zoom levels based on the location, but it’s usually around 21 (i.e. you can enter a decimal ranging from 1 to 21). See how it works below.

_Testing the zoom option_
**Latitude and Longitude**
Lastly, we need to select the **coordinate** fields from our Airtable data we had prepared earlier.

_Latitude and Longitude_
### **Marker Option**
Finally, you need to configure the map marker. Apart from the **Color**, you need to define the **Title** of each location to be shown inside a pop-up when clicking on the location.
Further down, you can see how we configure the marker settings.
### **Dynamic Fields**
You can add any number of additional fields that will be displayed inside a pop-up that appears when the user clicks on the location. Below, you can see how we set up the marker along with dynamic fields. We add **Image** and **URL** fields and check how they appear inside the location pop-up.

_Setting app the marker settings_
---
# Header
Source: https://docs.softr.io/building-blocks/header
The header area of the site is usually used to display the navigation bar, logo, signin/signup , and can include other functionality depending on the nature of the site. Softr has several header layouts with different types of links and buttons that can be customized according to your requirements.
# Common Header Features
## Logo
All the Header block layouts have a **Logo** field that can be removed or changed by clicking on it. You can upload an image or choose one from the library.

_The “Logo” field_
## Buttons and links
Apart from the logo, there are **Buttons** and **Links**, which can also have **Sublinks** that appear within a dropdown opened when hovering over or clicking the link. Each layout has certain links and buttons by default, but you can add as many as you wish.

_Links and sublinks_
The links have a text area to enter the link name and an **Add action** button to specify what the link does. The action can be set to **Open Page, Scroll to section**, **Open external url,** or **Sign out**

_Link actions_
A **Sublink** can be added to the link by clicking the **Add sublink** option.

After adding a **Sublink**, the **Add action** option of the link becomes unavailable, as its only action now is to display the sublinks. Sublinks are configured similar to Links.
**Buttons** have a configuration similar to that of **Links**. The only difference is the visual layout.
## Show User Profile
This option is typically used to show a user profile icon with a dropdown to logged-in users. By default, you have the **Sign Out** and **My Profile** links, but you can add as many additional options as needed as well as remove the default ones.

_Show user profile_
You can see how this option is applied in [this tutorial](/11ba304436ed4354a8669d4869624b9c) on setting up Memberships.
## Sticky Header
Lastly, there is the **Always show the header on top of the screen** option. When enabled, the header will become sticky and will stay on the screen when scrolling down.

That's it for the overview. You can explore each layout in greater detail in the subsections to this article.
# Header Layouts
## Header with sublinks and button

_Header with sublinks and button_
This layout has a button and several **Links**, one of which has **Sublinks**. The dropdown with **Sublinks** opens on click.
## Header with links and buttons

_Header with links and buttons_
This layout has several **Links** and two **Buttons**, which are meant as **Sign In**
and **Sign Up** buttons but can also be customized to serve a different purpose.
## Header with hamburger menu

_Header with hamburger menu_
In this layout, the **Link** items appear under the hamburger menu. Here you can add **Links** only (no **Buttons**), and they will all appear within the hamburger menu, as shown below.

_Menu expanded_
## Header with sublinks, icon and description

_Header with sublinks, icons, and description_
This layout has an option to add an **Icon** and **Description** to **Sublinks**, which appear when hovering over the parent link, as shown above.
In the screenshot below, you can see what the icon and description configuration looks like.

_A sublink with a description and icon_
The **Icon** image can be customized by clicking on it and either uploading a new image or choosing one from the library. The **Description** is a text area, where you can add longer texts with multiple lines to describe the item.
---
# Hero
Source: https://docs.softr.io/building-blocks/hero
The "Hero" area is a large area at the top of the page (usually full width) that is supposed to give the user a general idea of what the website is about. If you are offering a certain product, the Hero are is usually the place where you put the value proposition of your product, summarizing what problems the product solves, what value it delivers to its customers, how it differentiates itself as the preferred provider of this value, and so on.
Hero areas often contain images, videos, dynamic text, etc. Softr offers a variety of layouts for the Hero block to choose from. In this section, we'll review all the layouts to give you a better understanding of how they can be configured and applied.
First, let's examine the features that all or most of the layouts have in common. Afterwards, we'll investigate the specifics of each layout one by one.
# Common Hero Block Features

_Hero block structure_
As you can see in the above image, the Hero block usually has the following components:
- **Title**
- **Subtitle**
- **Image/Video**
- **Buttons**
Let's take a closer look at each component.
## Title and Subtitle
The **Title** and **Subtitle** are simple text areas where you can add main and secondary text.

_Title and Subtitle_
## Image/Video
Next, you can add a an **image** or a **video** to accompany the text. Below the image/video field there is an option to switch the image position as well as an option to upload a background image for the whole Hero area.

_Adding an image to the Hero block_
## Buttons
Lastly, you have the **Button** element, which is a regular button with **Open page, Scroll to section**, and **Open external url actions**. You can also add more buttons with **Add button** below.

_Button actions_
# Hero Block Layouts
## Layout: Hero with call to action

_Hero with call to action_
This layout has all the features discussed in the [block overview](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/hero/avyLWEvNZNUqYewF51kMLA). It has an **Image/Video** area, a **Title** and a **Subtitle,** as well as a call to action button at the bottom.
## Layout: Hero with email capture

_Hero with email capture_
This layout has the common **Image/Video**, **Title**, and **Subtitle** fields, but instead of a CTA button it has an email capture.

_Email capture_
The email capture has an **Email input** where the user is supposed to provide his/her email address, and a **Button** next to the input to complete the action. As you can see in the screenshot above, the button has various possible actions to be attached to it. You can learn more about the different service integrations listed here in the [Integrations](/integrations/etS18kJqm1fuD58KCsjC3z/mailerlite/i1Ex2KK1HwqsceB1SnYWby) section.
## Layout: Hero with video

_Hero with video_
This layout allows you to add a video through URL (e.g. YouTube) to be opened in a pop-up after clicking on the play button (you can modify the background under the play button as well).

_Adding a video to the Hero block_
## Layout: Hero with appstore buttons

_Hero with video_
This layout allows you to add a video through URL (e.g. YouTube) to be opened in a pop-up after clicking on the play button (you can modify the background under the play button as well).

_Adding a video to the Hero block_
## Layout: Hero with email capture and typewriter

_Hero with email capture and typewriter_
This layout has an **Email capture** similar to the [Hero with email capture](/59b829b4b58f417fa4b6cff5f7c6a658) layout, but it also has a typewriter effect as shown in the animation above.
In the screenshot below, you can see how the typewriter effect is customized.

_Typewriter settings_
In the first **Title** field you provide the static text, while in the second **Title** below you are supposed to add the changing pieces of text separated by a comma. Each piece is typed in and is then replaced by the next piece, as you could see in the animation.
Next we have **Type Speed** and **Delete Speed**. Here you set how many milliseconds it should take for one letter to be added/deleted. In the animation below, we've applied a slower transition speed (both **Type Speed** and **Delete Speed** are set to 1000 milliseconds = 1 second), so that you can see how it works.

_Testing the typewriter_
---
# CTA
Source: https://docs.softr.io/building-blocks/cta
This is a simple block with some text and one or more CTA buttons that accomplish certain actions. The block has a **Title**, **Subtitle**, and a **Button(s)**.

_CTA Block_
# Common Block Features
## Title, Subtitle, and Background Image
These settings are located under the **Features** tab of block settings, and here you customize the **Title** and **Subtitle** texts and can add a **Background Image** for the whole block.

_Title, Subtitle, and Background Image_
## Button
By default, there's only one button, but you can use the **Add Button** option to add more buttons.

_Adding a button_
In the [Call to action with email capture](/6772b65a34c84bfdbe1bc16e8b03f525) layout the button allows to capture the user's email, but in the rest of the layouts it has the following **Action** options:
- **Open page** to open another page within the app;
- **Scroll to section** to scroll to a specific section within the page;
- **Open external url;**
- **Open Modal** to open another page within a pop-up.

_Button actions_
# CTA Block Layouts
## Layout: Call to action with a button

_Call to action with a button_
A layout with a button positioned at the bottom of the block.
## Layout: Call to action with email capture

_Call to action with email capture_
In this layout, instead of a simple CTA button, you have an email capture area. You can set the button **Action** to send the captured email to one of the supported services (more details in the [Integrations](/integrations/etS18kJqm1fuD58KCsjC3z/mailchimp/2GvSLRGrgMfe8S3drMWao1) section) or simply forward it to the specified email address.

_Button actions_
## Layout: Call to action with a button on the right
This layout is similar to the Call to action with a button but the button is positioned on the right hand.

_Call to action with a button on the right_
## Layout: Call to action with a text and action button

_Call to action with a text and action button_
This is a layout with a large text on a dark background and a CTA button.
---
# Feature
Source: https://docs.softr.io/building-blocks/feature
While the [Hero](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/hero/avyLWEvNZNUqYewF51kMLA) area is for giving some general idea about your product and emphasizing its value proposition, the **Feature** block is supposed to go a bit more into details, providing concise information on the key features of the product and what they allow the users to achieve. The block has several layouts, which we'll discuss separately in the following articles, but let's first check out how the block configuration is organized in general, and what are the key settings.
The block has 4 key components:
- **Title**
- **Subtitle**
- **Image**
- **Features List**

_Feature block structure_
Let's check how each component is configured.
## Title and Subtitle
These are two text areas where you can enter the text.

_Title and Subtitle_
## Image and Background Image

_Image and Background Image_
Here you can add an image (either upload or select from gallery) by clicking on the image icon as well as enter an "alt" text for the image (specifies an alternate text for an image if the image cannot be displayed).
Next, you have the option to change the **Image Position**. It can be set to either **Left** or **Right**. Lastly, there is a field to upload a **Background Image** for the whole **Feature** area. The animation below shows the process of configuring this section.

_Adding an Image and Background Image to the Feature block_
## Features
In this section you add the features along with their **Title**, **Description**, and **Icon**.
The features are added within separate tabs as shown below. There's also a plus button for adding a new feature tab as well as a delete option to delete the current feature.

_Add and Delete options_
You can also reorganize the tabs using drag and drop.

_Reorganizing tabs_
# Feature Block Layouts
## Layout: Feature with right side picture

_Feature with right side picture_
This layout has a one-column list of features and the image is on the right by default.
## Layout: Feature with left side picture

_Feature with left side picture_
In this layout, the features list is organized into two columns, and the image is on the left side by default.
## Layout: Feature with link

_Feature with link_
In this layout, the features don't have a subtitle field (only title) and are organized into one column, as can be seen in the image above. Moreover, there's a link at the bottom, the **Text** and **Action** of which can be customized, as shown below.

_Link setup for feature_
## Layout: Feature with product demo

_Feature with product demo_
This layout allows you to add an image to the feature to demonstrate it.

_Image option for each feature_
The users can switch between between the features to view each one, as shown below.

_How the block works_
---
# Feature Grid
Source: https://docs.softr.io/building-blocks/feature-grid
The Feature Grid block displays a collection of items in a grid layout. As the name suggests, it is meant to be used for listing product features, however, it can be also used for displaying any sort of lists (in some cases, the [List block](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU) may be more relevant depending on your use case). Let’s explore the block setting to see how it’s configured.
## Header
In the **Header** section of block settings, you can customize the **Title** and **Subtitle** as well as add a background image for the whole block.

_Feature Grid’s Header section_
## Features
In the Features section, you can customize each feature’s icon/image, title, description, as well as the link. Also, you can add new features, delete existing ones, as well as reorganize those.

_Customizing the Features section_
# Feature Grid Block Layouts
## Layout: **Feature grid with big icons**

_Feature Grid with big icons_
This Feature Grid layout features icons to illustrate each feature.
## Layout: Feature grid with four column view

_Feature Grid with four column view_
This Feature Grid layout is organized into four columns and features an image with overlay, which in turn contains a button.
## Layout: Feature grid with images

_Feature Grid with images_
A Feature Grid layout with images to illustrate each feature.
## Layout: Feature grid with small icons

_Feature Grid with small icons_
This Feature Grid layout is similar to Feature Grid with big icons but has smaller icons, which are positioned to the left from the Title and Subtitle.
## Layout: Feature grid with sections

_Feature Grid with sections_
This Feature Grid layout is organized into two columns and has bigger areas/sections for each item.
## Layout: Feature grid with three column view

_Feature grid with three column view_
A Feature Grid layout with three columns.
## Layout: Feature grid with box and three column view

_Feature grid with box and three column view_
A Feature Grid layout with boxed items organized into three columns.
## Layout: Feature grid with steps

_Feature Grid with steps_
This Feature Grid layout lets you present your items in a “steps” format.
---
# Partner
Source: https://docs.softr.io/building-blocks/partner

_Partner block_
Using the **Partner** block you can present your partners, key customers, and so on. The block consists of a **Title**, **Subtitle**, and a list of partner logos. Let's see how each of those is configured.
## Title and Subtitle

_Title and Subtitle_
Here you enter the **Title** and **Subtitle** texts.
## Partners
In this section you add the partners along with their **Image** and **Link.**
Each partner item is added within a separate tab. You can add new tabs, delete, and reorganize them. Additional rows will be added depending on the number of partner items. Check out the gif below to get a better idea.

_Configuring the Partner block_
# Partner Block Layouts
## Layout: **Partner with fixed logos**

_Partner with fixed logo_
In this layout, the grid with partner logos is static, and new rows are added as the number of logos increases.
## Layout: **Partner with sliding logos**

_Partner with sliding logos_
In this layout, all the logos are presented through a sliding animation in a single row, as shown above.
---
# X (Twitter) Grid
Source: https://docs.softr.io/building-blocks/x-twitter-grid
The X Grid block lets you embed one or more X posts into your Softr app. The block allows adding URLs of separate posts from different accounts, so you can, for instance, showcase testimonials about your product from all over the X.
> **Note**
>
> You can also use **X (Twitter) Dynamic Block** to pull X post URLs from your data source.
## Setting up the X Grid block

First come the **Title** and **Subtitle** fields, which you can customize depending on your needs. You can use it as a ‘Wall of love” that can showcase positive testimonials about your product.
Next, we have the **Posts** section, where we can add as many individual posts as needed:

## Setting up X Dynamic block

Step 1: Prepare URLs of X posts in on of your [Data Sources](/07f4b2dc85804906af97fdf3f1dda0ea):

_Using Google Sheets as an example data source_
Step 2: Choose a source where URLs of your X posts are:

_Google Sheets used as source of X posts_
Step 3: Under Content tab, map your source field having X post URLs:
---
# Quick Links
Source: https://docs.softr.io/building-blocks/quick-links
## When to use Quick Links
Our Quick Links block looks like a dynamic list block, but it’s actually a super convenient way to show a polished grid of tiles to act as links to other pages in your app or even external URLs. Here’s when it might make sense to use the Quick Links block:
- Showing a list of most commonly accessed forms in your Softr app
- Providing users quick access to a list of external tools or sites.
- Displaying a customized list of links to other pages based on [User Group](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/user-groups/6XQfKMeKHUvBcAjKvLs3g3).
- Showcasing a list of static features, icons, or images - maybe you don’t need to link to anything!
## Adding a Quick Links Block
To add a Quick Links block:
1. In Softr Studio, open your app and navigate to the page in your Softr app that you want to add the block to.
2. Hover over and click on the plus icon on the page.
3. Select the **Static** tab to open the list of Static blocks.
4. Open the **Quick Links** dropdown and select the Quick Links block to add it.

## Features and Settings
### Content
Access the main features and settings of the Quick Links block by clicking on the block and selecting the **Content** tab.
- **Title and Subtitle**: Toggle this on to add a Title and Subtitle to the block to explain what the quick links are about or how and when a user should use them.

- **Layout**: Choose between horizontally oriented cards or vertically oriented cards. Here you can also control the card width, the card’s content alignment, whether to use icons or images, the label/icon position, whether to show or hide the arrow guidance icons, and other options.

- **Links**: Here you can add or remove links and customize their name, their icon/image, and change where they link to and how the link should be opened.

- **Embed**: Once you have published your application, you can get an embed code to embed just the Quick Links block in another website or application. Note that if the block is behind a user group or login, it may not be visible. If you plan to Embed the block, make sure it’s publicly accessible.

### Styles
In this tab, you can edit the overall styling of the Quick Links such as rounding, card colors, title and subtitle fonts/colors, and more. Note that much of the styling is inherited from the [app theme](/styling/7qXYEkNvWQamR6vcLXzZnF/application-theme/91YGSL2aDJajXdbPBhitbc) itself.

### Visibility
As with all blocks, you can show or hide the entire block based on user group or even device type. Read more about block visibility [here](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/block-visibility/3spA2dfQNrcGcPNmnDXHB3).

---
# Pricing
Source: https://docs.softr.io/building-blocks/pricing
Pricing blocks are drop-in sections for showing plans, tiers, or package prices. They live under the **Static** tab in the block library and cover everything from a simple three-tier layout to a full comparison table or an interactive price calculator.
Every Pricing block is editable two ways, side by side:
**AI chat**
Describe what you want in plain English and Softr rewrites the whole block for you — names, descriptions, prices, features, button labels.
**Content settings**
Open the **Content** tab and edit any field by hand. This is exactly the same data the AI writes to, so you can switch between the two at any time.
You don't have to pick one approach. Most people use the AI to get 90% of the way there, then polish specific values (a price, a line of copy, a button link) in the settings panel.

_A freshly added Centered Pricing block. The right-panel tabs are the full editing surface — Chat is the AI, Content is the manual settings the AI writes to._
## Adding a Pricing block
1. **Open the page**
Open the page you want the block on.
2. **Open Browse blocks**
Click an empty area of the canvas (or the **+** between two blocks) to open **Browse blocks**.
3. **Switch to the Static tab**
The Pricing category lives here, alongside Hero, CTA, Team, Testimonial, and FAQ.
4. **Pick a variant**
Expand the **Pricing** category and click the variant you want.

The block lands on the canvas with placeholder content (three tiers, sample features, sample prices). The settings panel opens on the right with **Chat** already selected so you can start iterating immediately.
### Pricing variants at a glance
Softr ships 11 Pricing variants. They all share the same underlying content model, so switching between them is safe — your plans, prices, and features carry over.
**Centered**
Three-tier layout with a centered header and a highlighted "Most popular" card.
**Split header**
Heading on the left, plans on the right.
**With cover image**
Three tiers with illustrated imagery above each card.
**Multi color**
Three tiers with distinct colored backgrounds per card.
**With background pattern**
Three tiers on a decorative patterned background.
**With custom plan**
Three tiers plus a wider custom/enterprise row underneath.
**Hovered card**
Three tiers where the middle card lifts on hover.
**Simple table**
Comparison table with features in rows and plans in columns.
**Card grid**
Feature matrix presented as a grid of cards.
**Plan recommender**
Interactive quiz that recommends a plan based on the visitor's answers.
**Price calculator**
Slider/input driven calculator that produces a live price estimate.
> **Info**
>
> The first nine variants are purely presentational. **Plan recommender** and **Price calculator** include interactive logic — editable the same way, but with extra settings for the quiz questions or calculator inputs.
## Editing with AI (the Chat tab)
Click the block on the canvas. The right panel opens with **Chat** active and a greeting: _"Hi, you can ask me to make edits to this block!"_ Type what you want and hit send.

### What the AI can rewrite in one go
A single prompt can set any combination of:
- Block title and description
- Each tier's plan name, tagline, monthly price, and yearly price
- Each tier's feature list (including the "Everything in X, plus:" label on higher tiers)
- The CTA button text and link for each tier
- Which tier is badged **Most popular**
### A worked example
> **Note**
>
> **Prompt:** Change the pricing to three tiers for a photography studio: Basic $99, Standard $249, Premium $499. Update features to match.
Within a few seconds the block renders new tiers — Basic, Standard, Premium — with photography-appropriate features ("1-hour photo session", "Online gallery for 30 days", "Commercial use license") and button labels ("Book now") that match the new context.

_The AI writes to the same fields you'd edit manually — so the new content shows up in the Content tab too._
### Iterating with follow-up prompts
The chat is conversational. Use short follow-ups rather than rewriting from scratch:
- _"Make the middle tier not most popular, highlight Premium instead."_
- _"Add a 'Print album included' feature to the Premium tier."_
- _"Change the billing period from monthly to per session."_
- _"Drop the yearly prices, I only offer monthly."_
Each prompt produces a new version — see [Versions and rollback](#versions-and-rollback) below.
> **Warning**
>
> **What the AI can't do.** The AI edits the _content_ of the block. It doesn't change the structural layout (it won't turn a Centered variant into a Table variant — you switch variants from the block library), and it doesn't wire up payment processing. To take payments, connect the CTA button to a Stripe checkout URL or a custom workflow via the **Actions** tab.
> **Tip**
>
> **Attach a reference image.** The composer has a small image icon at the bottom left. Attach a competitor's pricing screenshot or a mood board and ask the AI to "match the tiers and pricing structure from this image" — handy when you're porting pricing over from an existing source.
> **Info**
>
> **Credits.** Every AI edit consumes a small number of AI credits — typically well under one credit per prompt. After the AI replies, a credit cost appears under the message (e.g. _"0.89 credits used"_). Credits are scoped to your workspace plan; tight loops of small follow-up prompts are cheap.
## Editing in the Content tab
Open **Content** to see every field the AI is writing to. Whether you got here after an AI edit or you're starting fresh, the layout is the same.

The Content tab has two inner modes:
**Settings**
The structured editor described below. This is what most people use, **_but could change depending on what you prompt the AI_**.
**Code**
The raw JSON for the block. Advanced users can paste a block definition from another project, diff two versions, or hand-craft content that's easier to express as data.
### Block-level fields
At the top of Settings:
- **Title** — big heading at the top of the block (e.g. "Pricing").
- **Description** — smaller subheading below the title.
- **Popular badge text** — text shown on the highlighted plan's badge. Defaults to "Most popular".
- **Monthly button text** / **Yearly button text** — the labels on the billing-period toggle above the plan cards. Edit these if you want different wording (e.g. "Per month" / "Per year") or if you're showing something other than monthly/yearly (e.g. "Per session" / "Per project").
### Pricing plans
Below that, the **Pricing plans** list shows every tier as a draggable, collapsible row. Hover a row to reveal the trash and drag handles. Click the chevron to expand and see the plan's own fields.

In this case, each plan has:
- **Plan name** — e.g. "Basic", "Standard", "Premium".
- **Description** — one-line tagline under the name (e.g. "Getting started").
- **Monthly price** / **Yearly price** — free-text, so `$99`, `£79`, `€49 + VAT`, or `Contact us` all work.
- **Features label** — the line above the feature list. Leave blank on the first tier; use "Everything in Basic, plus:" style text on higher tiers.
- **Features** — the bullet list. Each feature is its own draggable row with a trash icon. **+ Add item** adds a new one.
- **Is most popular** — a per-plan toggle. Turning it on adds the Most popular badge to that tier. Only one plan should have this enabled at a time.
- **CTA text** — the button label on that card.
- **CTA URL** — where the button goes. Softr shows a dropdown of existing app pages; you can also paste an external URL or connect to a workflow.
To reorder plans, drag a row by its handle. To add a plan, click **+ Add item** at the bottom of the list.
## Versions and rollback
Every AI edit is saved as a version. Above the Settings editor you'll see a **Version 1** dropdown with a chevron — open it to see the history.

Each version records:
- The prompt that produced it (or "Initial Version Prompt" for the starting template).
- The date and time.
- The label **(Latest)** on the current one.
> **Success**
>
> Pick any version to roll the block back. This is the easiest way to recover from a prompt that didn't go the way you wanted — no undo stack, no copy-paste, just a single click.
## Connecting a data source (optional)
> **Info**
>
> Pricing blocks are static by default — the prices and features live in the block itself, not in a database.
The **Source** tab is there for the one case where you want the block driven by a table: a banner reading _"Data source is optional"_ appears at the top, and below it are dropdowns for Source, Database, and Table. Connect a table and each row in that table becomes a plan card.
Use this when your pricing changes often, you have more than \~6 tiers, or you want non-technical teammates to edit pricing by editing a spreadsheet rather than touching the Studio.
## FAQ
**If I use the AI and then edit a field in Content, will my next AI prompt overwrite what I edited?**
It might. The AI rewrites whichever fields your prompt implies are in scope. Narrow prompts ("change the Standard tier price to $299") touch only that field; broad prompts ("rewrite the whole pricing section for a consulting business") will reset most fields.
If you've made manual tweaks you want to keep, either rely on version history (every AI edit is saved automatically — see [Versions and rollback](#versions-and-rollback)) or include your tweaks in the prompt ("keep the current features on Basic, just change the price").
**How are AI credits charged for the chat edits?**
Each prompt-response pair costs AI credits — usually well under one credit for a single pricing edit. You can see the exact cost under each AI reply via the info icon. Credits are pooled at the workspace level and replenish based on your Softr plan; check **Settings → Billing** for your current allowance.
**Can the AI change the block's visual layout — e.g. turn Centered into Simple table?**
No. The AI edits content within the current variant. To switch layouts, delete the block and add a different variant from the library, or pick a variant and then re-run your AI prompt — the copy you wrote works the same across variants because they share one content model.
**My pricing is "Contact us" — can I put non-numeric text in the price field?**
Yes. Monthly price and Yearly price are free-text, so `$49`, `£29.99/mo`, `Contact us`, and `Custom` all render correctly. The billing-period toggle still applies, though — if you only have one price, either set both Monthly and Yearly to the same value, or word the button text to match what you're actually charging for.
**How do I wire the CTA button to a real checkout or signup flow?**
Set **CTA URL** to the destination you want — that can be another page in your app, an external URL (e.g. a Stripe Checkout link), or a linked workflow. For logged-in users you can stamp the submission with the user's email or record ID via the **Actions** tab; see the [Mapping Fields for Actions](/actions/mapping-fields-for-actions) doc for the full field-mapping flow.
---
Last updated: April 2026. If something in this doc looks wrong or out of date, please contact support.
---
# Vibe Coding
Source: https://docs.softr.io/vibe-coding
The Vibe Coding Block lets you go beyond Softr's standard blocks to build fully custom interfaces — all from a prompt. By isolating AI code generation to individual UI blocks, Vibe Coding acts as the ultimate extension layer and safety net. You get the limitless flexibility of "vibe coding" without the risk of breaking your app's global security or core infrastructure. Connect it to your live data, add CRUD actions, and create personalized experiences to move beyond generated prototypes into bespoke production apps. Build and iterate confidently with version history built in, and make simple text and image edits directly without re-prompting.
## What can you build?
Client dashboards, booking tools, progress trackers, calculators, notification feeds, partner portals, and more. Check out the videos below for examples.
## Step-by-step: Using the Vibe Coding Block
### 1. Add the Vibe Coding Block and enter your prompt
Open your Softr app, click **Add block**, then select **AI → Vibe Coding Block**.
In the chat, describe what you want to build in plain English. The Vibe Coding Block supports both static and data-connected blocks. For example:
- A static layout like a page header, pricing table, or content section
- A dynamic, data-connected block like a dashboard, booking tool, or admin view that pulls from live data
You can also attach an image to your prompt (click the image icon in the bottom left of the chat box), which is useful for sharing a design reference or screenshot of what you're going for.
Once you submit your prompt, Softr's AI generates the interface inside the block. To connect a live data source, see Step 2.

### 2. Connect a data source (optional)
If you want your block to dynamically display live data, go to the **Source** tab and connect a data source (Database + Table). You can also add conditional filters here.
The Vibe Coding Block supports Softr Databases and 15+ [external data sources](https://www.softr.io/integrations), including Airtable, Google Sheets, Notion, HubSpot, SQL, and more.

### 3. Add and configure CRUD and other actions (optional)
You can prompt the AI to add action buttons, such as:
- Create/add records
- Edit/update records
- Delete records
- Ask AI
After generating these functionalities in the UI, you can:
1. Go to the **Actions** tab in the vibe coding block
2. Review each action and configure permissions, conditions, or connected workflows as needed
For example, you could prompt: _"Add a button that lets users submit a new booking request"_ — the AI will generate the UI and create a corresponding action you can configure in the Actions tab.
### 4. Control visibility and access
Use the **Visibility** tab to control which user groups can see the block. You can also set conditional filters in the **Source** tab.

## Managing version history
Each time you re-prompt the block, Softr saves a new version. This lets you experiment without losing earlier work.
### Using Undo
For quick corrections, you can use the **Undo** button located directly in the AI chat on the last message. Clicking **Undo** instantly reverts the block to its immediate previous state.
### Reverting and duplicating versions
To view or revert to any previous version:
1. Open the **Content** tab
2. Use the version dropdown at the top of the tab
3. Select a previous version and click **Restore** to revert (or **Duplicate as new** to duplicate the block)

## Editing text in the vibe-coded block
From the **Content** tab, go to **Settings** to edit text fields directly — for example, hero text, testimonials, or images. This option appears when the AI has generated editable text fields in your block.

## Editing the generated code
If you want to make manual changes beyond what the AI generates, you can edit the underlying code yourself. Go to the **Content tab → Code** to see the full generated code. Make your changes and click **Save** to apply them.
You can use the AI chat for bigger structural changes and drop into the code for fine-tuned adjustments — both approaches work together.
## Copying the block to another project
To reuse a vibe-coded block in a different Softr project, hover over the block until the action icons appear on the right side. Click the **Copy to** icon and select the destination project. This is useful for replicating tools or UI patterns across client portals or apps.
## Pricing and AI credits
The Vibe Coding Block uses AI credits. A certain number of monthly credits is available on each plan (including Free). Learn more about AI credits [here](https://docs.softr.io/workspace-and-billing/ai-credits).
---
# Vibe Coding — Developer Guide
Source: https://docs.softr.io/vibe-coding-developer-guide
This guide is for developers who want to write code directly in the Vibe Coding Block, rather than prompting the AI. Use it when you need full control over your block's markup, logic, and data.
---
## The Basics
Block's source code is a TypeScript file with a default-exported React component:
```tsx
export default function Block() {
return (
Hello, world!
);
}
```
This only runs in the browser - you can fetch and mutate data from connected data sources, but you cannot run server-side code or use Node.js APIs.
Vibe coding block is configured to use [Tailwind](https://tailwindcss.com/) for styling and [shadcn/ui](https://ui.shadcn.com/) for components, but you are free to import any public npm package as needed. In fact, any npm package import you add will automatically install it for you.
```tsx
import { format } from "date-fns"; // will be resolved at compile time
export default function Block() {
const today = format(new Date(), "MMMM d, yyyy");
return
Today's date is {today}
;
}
```
---
## shadcn/ui
shadcn/ui components are already pre-configured and follow your app's theme out of the box. They're available under the `@/components/ui` path, so you can import them like this:
```tsx
import { Button } from "@/components/ui/button";
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
```
Currently the following components are available:
`accordion`, `alert`, `alert-dialog`, `aspect-ratio`, `avatar`, `badge`, `button`, `calendar`, `card`, `carousel`, `chart`, `checkbox`, `collapsible`, `command`, `context-menu`, `dialog`, `drawer`, `dropdown-menu`, `empty`, `hover-card`, `input`, `input-group`, `input-otp`, `item`, `kbd`, `label`, `menubar`, `native-select`, `navigation-menu`, `pagination`, `popover`, `progress`, `radio-group`, `resizable`, `scroll-area`, `select`, `separator`, `sheet`, `skeleton`, `slider`, `sonner`, `spinner`, `switch`, `table`, `tabs`, `textarea`, `toggle`, `toggle-group`, `tooltip`
Check out the [shadcn/ui docs](https://ui.shadcn.com/docs/components) for usage details and examples for each component.
### Icons
Preferred icon pack is [Lucide Icons](https://lucide.dev/), but you can opt for a different one.
```tsx
import { TrendingUp, User, Settings } from "lucide-react";
```
### Styling
We follow the default shadcn/ui naming convention for background/foreground color pairs (e.g. `bg-primary` / `text-primary-foreground`) which maps to your app's theme colors.
By default, block occupies full width of the page but special classes - `container` and `content` are available to constrain the width of content to match app's max width settings to ensure visual consistency with other blocks:
```tsx
{/* your content here */}
```
## Data from Your Datasource
Import data hooks from `@/lib/datasource`. Use these when you want to display records from your connected data source. All data fetching hooks follow a query builder pattern so you can be quite expressive with your queries.
### One or many datasources
A block can connect to multiple datasources. When it does, every fetch or mutation needs to say which datasource it targets. The `datasource.define` utility gives you readable aliases for that. Declare it once at the top of the file, then pass the alias as `from` on each hook:
```tsx
import { datasource, useRecords, q } from "@/lib/datasource";
const ds = datasource.define({
orders: "ds_id_1",
customers: "ds_id_2",
});
const ordersSelect = q.select({ product: "field1", total: "field2" });
const customersSelect = q.select({ name: "field3", email: "field4" });
export default function Block() {
const { data: orders } = useRecords({ from: ds.orders, select: ordersSelect });
const { data: customers } = useRecords({ from: ds.customers, select: customersSelect });
// ...
}
```
With a single datasource you can skip `datasource.define` and omit `from`. The hooks then default to that one datasource. As soon as a block has more than one, leaving out `from` throws an error, since the hook can't tell which datasource the call belongs to.
Every record hook takes `from` the same way: `useRecords`, `useRecord`, `useLinkedRecords`, `useFieldOptions`, `useMetric`, `useChartData`, `useRecordCreate`, `useRecordUpdate`, and `useRecordDelete`. `useUpload` and `useCurrentRecordId` work at the app level and thus `from` is not applicable to them.
### Defining a select query
Field mappings have to be static, we also use static analysis to determine which fields your block actually uses so we don't overfetch and don't accidentally expose potentially sensitive data.
```tsx
import { q } from "@/lib/datasource";
const select = q.select({
title: "FIELD_ID1", // key = alias used in code, value = actual field ID
description: "FIELD_ID2",
createdAt: "FIELD_ID3",
});
```
> **Note**
>
> For \*\*Airtable, Notion, and Google Sheets \*\* datasources do not use field IDs in this context — use the **field name** as the value instead (e.g. `title: "Name"` rather than `title: "fldXXXXXX"`).
So something like this is not allowed as it breaks static analysis:
```tsx
const select = q.select({
[dynamicKey]: "FIELD_ID1", // ❌ dynamic keys not allowed
title: getFieldId(), // ❌ dynamic values not allowed
});
```
### `useRecords` — fetch a list of records
```tsx
import { useRecords, q } from "@/lib/datasource";
export default function Block() {
const {
data, // array of pages with shape { items: Record[]; total: number; offset: string | number | null }
status, // "pending" | "success" | "error"
error, // Error object if status is "error"
fetchNextPage, // function to fetch the next page of results
hasNextPage, // boolean indicating if there are more pages to fetch
isFetching, // boolean indicating if any page is currently being fetched
isFetchingNextPage, // boolean indicating if the next page is currently being fetched
refetch, // function to refetch the data (e.g. after a mutation)
isRefetching, // boolean indicating if a refetch is currently in progress
isRefetchError, // boolean indicating if the last refetch resulted in an error
} = useRecords({
select: q.select({
name: "FIELD_ID1",
email: "FIELD_ID2",
}),
count: 6, // records per page, default 6, max 100
// from: ds.orders, // datasource alias, required when the block has multiple datasources
// where: ..., // optional filter
// orderBy: ..., // optional sort
// enabled: ..., // optional boolean to defer loading (e.g. until component is visible)
});
if (status === "pending") return
);
}
```
### `useRecord` — fetch a single record by ID
Use with `useCurrentRecordId()` to display details of the record currently shown in a list/detail context:
```tsx
import { useRecord, useCurrentRecordId, q } from "@/lib/datasource";
export default function Block() {
const recordId = useCurrentRecordId(); // resolves the ID of the current record from page, can also be null
const { data, status } = useRecord({
select: q.select({
title: "FIELD_ID1",
description: "FIELD_ID2",
}),
recordId,
// from: ds.orders, // datasource alias, required when the block has multiple datasources
});
if (status === "pending") return
Loading...
;
if (status === "error") return
Error
;
if (!data) return
Not found
;
return (
{data.fields.title}
{data.fields.description}
);
}
```
### Filtering records
Use the `q` query builder for filters. Filters support up to **2 levels of nesting**.
```tsx
useRecords({
select,
where: q.and(
q.text("name").contains("Alice"),
q.number("age").gte(18),
q.or(
q.boolean("isActive").is(true),
q.text("notes").isNotEmpty()
)
),
});
```
**Available filter methods:**
| Builder | Methods |
| ------------------ | --------------------------------------------------------------------------------------------------------------- |
| `q.text(field)` | `is`, `isNot`, `contains`, `startsWith`, `endsWith`, `isOneOf`, `isNoneOf`, `hasAllOf`, `isEmpty`, `isNotEmpty` |
| `q.number(field)` | `is`, `isNot`, `gt`, `gte`, `lt`, `lte`, `between`, `isEmpty`, `isNotEmpty` |
| `q.boolean(field)` | `is`, `isNot`, `isEmpty`, `isNotEmpty` |
| `q.date(field)` | `is`, `isNot`, `gt`, `gte`, `lt`, `lte`, `between`, `isNotBetween`, `isEmpty`, `isNotEmpty` |
| `q.array(field)` | `is`, `isOneOf`, `isNoneOf`, `hasAllOf`, `isEmpty`, `isNotEmpty` |
| `q.and(...)` | combine filters with AND |
| `q.or(...)` | combine filters with OR |
### Sorting records
```tsx
useRecords({
select,
orderBy: q.desc("createdAt"), // or q.asc("createdAt")
});
// Multiple sort fields (tie-breakers):
useRecords({
select,
orderBy: [q.asc("lastName"), q.asc("firstName")],
});
```
### `useLinkedRecords` — fetch options from a linked table
Use for dropdowns, comboboxes, or tag pickers where you need to show values from a related table:
```tsx
import { q, useLinkedRecords } from "@/lib/datasource";
export default function Block() {
const {
data,
status,
error,
fetchNextPage,
hasNextPage,
isFetching,
isFetchingNextPage,
refetch,
isRefetching,
isRefetchError,
} = useLinkedRecords({
select: q.select({ category: "$CATEGORY_FIELD_ID" }),
field: "category", // alias from select that holds the linked field
sortOrder: "ASC", // "ASC" | "DESC"
search: "", // optional search term
enabled: true, // set false to defer loading (e.g. until dropdown opens)
// from: ds.orders, // datasource alias, required when the block has multiple datasources
// count: ..., // optional page size, defaults to 100, max 1000
});
const options = data?.pages.flatMap(p => p.items) ?? [];
return (
{options.map(opt => (
{opt.title}
))}
);
}
```
Each item only carries its `id` and `title` (the linked table's primary field). To read other fields off those records, connect the linked table as its own datasource and query it with `useRecords`. See [One or many datasources](#one-or-many-datasources).
---
## Mutating Records
All mutation hooks expose an `enabled` boolean — **always check it** before rendering the mutation UI or calling the function. It reflects whether the current user has sufficient permissions. If called without checking `enabled`, the mutation will throw an error.
### `useRecordCreate`
```tsx
import { useRecordCreate, q } from "@/lib/datasource";
import { toast } from "sonner";
export default function Block() {
const {
enabled, // boolean indicating if the user has permission to create records
mutate, // void function to create a record, accepts an object with shape from provided fields, in this case - `{ name: string; email: string }`
mutateAsync, // async version of mutate that returns a promise with the created record
status, // "idle" | "pending" | "success" | "error"
error, // Error object if status is "error"
reset, // function to reset the status and error state back to "idle" and null, useful for showing multiple create forms in a row
} = useRecordCreate({
fields: q.select({
name: "FIELD_ID1",
email: "FIELD_ID2",
}),
onSuccess: (newRecord) => toast.success("Created!"),
onError: (error) => toast.error(error.message),
// from: ds.orders, // datasource alias, required when the block has multiple datasources
});
return (
{enabled && (
)}
);
}
```
### `useRecordUpdate`
```tsx
import { useRecordUpdate, q } from "@/lib/datasource";
export default function Block() {
const { data, refetch } = useRecords({ ... });
const {
enabled,
mutate,
mutateAsync,
status,
error,
reset,
} = useRecordUpdate({
fields: q.select({ status: "FIELD_ID1" }),
onSuccess: async (updatedRecord) => {
// refetch the data first to ensure the UI shows the latest value before notifying the user.
await refetch();
toast.success("Updated!");
},
onError: (error) => toast.error(error.message),
// from: ds.orders, // datasource alias, required when the block has multiple datasources
});
const onUpdateClick = () => {
if (!enabled) return;
mutate({
recordId: "RECORD_ID", // ID of the record to update
fields: { status: "active" }, // updated field values
});
};
}
```
### `useRecordDelete`
```tsx
import { useRecordDelete } from "@/lib/datasource";
export default function Block() {
const {
enabled,
mutate,
mutateAsync,
status,
error,
reset,
} = useRecordDelete({
onSuccess: async ({ recordId }) => {
await refetch();
toast.success("Deleted!");
},
onError: (error) => toast.error(error.message),
// from: ds.orders, // datasource alias, required when the block has multiple datasources
});
const onDeleteClick = () => {
if (!enabled) return;
mutate("RECORD_ID"); // ID of the record to delete
};
}
```
### Phone fields
When writing to a `PHONE` field, the value must be in unformatted international format: `+` followed by digits only (e.g. `+12125550100`). Some datasources (such as Monday.com) reject values that contain spaces, dashes, or parentheses. Strip all non-digit characters except the leading `+` before submitting:
```tsx
const sanitizePhone = (raw: string) => raw.replace(/[^\d+]/g, "").replace(/(?!^)\+/g, "");
mutate({ phone: sanitizePhone(inputValue) });
```
---
## Uploading Files
Use `useUpload` from `@/lib/datasource` to upload files and get back a URL to store in a record.
```tsx
import { useUpload, useRecordCreate, q } from "@/lib/datasource";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { toast } from "sonner";
import { useState } from "react";
const fields = q.select({
name: "$NAME_FIELD_ID",
attachment: "$ATTACHMENT_FIELD_ID",
});
export default function Block() {
const [name, setName] = useState("");
const [file, setFile] = useState(null);
const { uploadAsync, isUploading } = useUpload();
const createRecord = useRecordCreate({
fields,
onSuccess: () => toast.success("Submitted!"),
});
const handleSubmit = async () => {
if (!file) return;
const [result] = await uploadAsync(file);
if (result.status === "completed") {
createRecord.mutate({
name,
attachment: { filename: result.file.name, url: result.url },
});
} else {
toast.error(result.error?.message ?? "Upload failed");
}
};
return (
);
}
```
For multiple files:
```tsx
const results = await uploadAsync(Array.from(e.target.files));
const completed = results.filter(r => r.status === "completed");
```
---
## Current User
Get info about the logged-in user with `useCurrentUser` from `@/lib/user`. Returns `null` if no user is logged in.
```tsx
import { useCurrentUser } from "@/lib/user";
export default function Block() {
const user = useCurrentUser();
if (!user) return
Please log in to continue.
;
return (
{user.avatar && (
)}
{user.fullName}
{user.email}
);
}
```
Available fields:
- `id`: `string | null` (only present when user sync is enabled)
- `fullName`: `string | null`
- `firstName`: `string | null`
- `lastName`: `string | null`
- `email`: `string | null`
- `avatar`: `string | null`
### Custom user properties
Beyond the reserved fields above, any custom fields that exist on your user record are available under `user.properties`. Pass a `properties` map to alias each field to a readable name, the same way a `select` query works.
```tsx
import { useCurrentUser } from "@/lib/user";
export default function Block() {
const user = useCurrentUser({
properties: {
stripeId: "FIELD_ID1",
plan: "FIELD_ID2",
},
});
if (!user) return
Please log in to continue.
;
return (
Welcome, {user.fullName}!
{user.properties.stripeId &&
Stripe ID: {user.properties.stripeId}
}
{user.properties.plan &&
Your plan: {user.properties.plan}
}
);
}
```
---
## Metrics & Charts
### `useMetric` — single aggregated value
Useful for KPI cards (total sales, average rating, etc.):
```tsx
import { useMetric, q, metric } from "@/lib/datasource";
export default function Block() {
const { data, status } = useMetric({
select: q.select({ revenue: "$REVENUE_FIELD_ID" }),
metric: metric.sum("revenue"),
// from: ds.orders, // datasource alias, required when the block has multiple datasources
// where: q.date("createdAt").gte("2025-01-01"),
});
if (status === "pending") return
Loading...
;
return
${data?.toFixed(2)}
;
}
```
**Aggregations:** `metric.sum(field)`, `metric.avg(field)`, `metric.max(field)`, `metric.min(field)`, `metric.distinct(field)`, `metric.count()`
### `useChartData` — grouped data for charts
```tsx
import { useChartData, q, metric } from "@/lib/datasource";
import { LineChart, Line, XAxis, CartesianGrid } from "recharts";
import { ChartContainer, ChartTooltip, ChartTooltipContent, type ChartConfig } from "@/components/ui/chart";
const chartConfig = {
revenue: { label: "Revenue", color: "var(--chart-1)" },
} satisfies ChartConfig;
export default function Block() {
const { data, status } = useChartData({
select: q.select({
date: "$DATE_FIELD_ID",
revenue: "$REVENUE_FIELD_ID",
}),
orderBy: q.asc("date"),
metric: { revenue: metric.sum("revenue") },
groupBy: metric.groupBy("date", metric.bucket.month.long),
// from: ds.orders, // datasource alias, required when the block has multiple datasources
});
if (status === "pending") return
Loading...
;
return (
} />
);
}
```
**Grouping buckets:**
| Bucket | Format example |
| -------------------------- | ---------------- |
| `metric.bucket.year` | `2025` |
| `metric.bucket.month.iso` | `"2025-03"` |
| `metric.bucket.month.long` | `"March 2025"` |
| `metric.bucket.day.iso` | `"2025-03-15"` |
| `metric.bucket.day.long` | `"Mar 15, 2025"` |
---
## Comments
Comments live on records. They're set up once for the whole app in **Settings → Comments**. The hooks in `@/lib/comments` give you one thread per record — you lay it out, the app owns the data, the copy and the permissions.
Don't build your own thread on top of a datasource field. Comments written that way are invisible to every other block in the app, and to the builder's moderation tools.
### `useCommentsSettings`
Every label, placeholder, empty-state message and the sort direction comes from here. A builder edits them in Settings → Comments and expects the change to show up right away, with no republish. So read them from the hook — don't hardcode strings.
Don't expose them as `useTextSetting` either. That's a second source of truth, and it quietly overrides the app's settings.
```tsx
function useCommentsSettings(options: {
/** Which layout you're building. The two layouts have separate display settings. */
displayAs: "BLOCK" | "SIDE_PANEL";
/** Which datasource the thread is on. Required on a multi-datasource block. */
from?: string;
}): {
commentListTitle: string; // may be empty — render no heading rather than an empty one
commentBoxPlaceholder: string;
submitButtonLabel: string;
deleteButtonLabel: string;
loadMoreCommentsButtonLabel: string;
emptyStateMessage: string; // shown instead of the list when the thread is empty
notificationsToggleLabel: string;
sortDirection: "NEWEST_ON_TOP" | "OLDEST_ON_TOP";
surface: boolean; // whether each comment sits on its own card
showVerticalLine: boolean; // whether a line joins consecutive comments into one thread
commentPanelDisplayMode: "PUSH_MAIN_CONTENT" | "COVER_MAIN_CONTENT"; // SIDE_PANEL only
canPost: boolean; // false for a viewer who can read the thread but not post
quickReactions: Array<{ emoji: string; label: string }>; // the only emoji this surface can post
allowMentions: boolean; // false when the app has mentions turned off
} | null
```
**`displayAs` picks which settings you get.** Settings → Comments has two separate sets of display options, one per layout. Pass `"BLOCK"` for a thread in the block's own flow, `"SIDE_PANEL"` for a docked panel. Pass the wrong one and the builder's edits look like they do nothing.
**Keep the field names when you destructure.** `commentListTitle` is the "Comment list title" setting, `submitButtonLabel` is "Submit button label". Rename it to `title` and the link to the control the builder edits is gone.
**`null` means render no comments UI at all.** You get it when the app has no comment settings, when that table isn't registered for comments, or when the viewer can't see the thread. It's not an error, and it's not a reason to fall back to something of your own.
```tsx
import { useCommentsSettings } from "@/lib/comments";
export default function Block() {
const settings = useCommentsSettings({ displayAs: "BLOCK" });
if (!settings) return null;
return (
{settings.commentListTitle &&
{settings.commentListTitle}
}
{settings.canPost && (
)}
);
}
```
The rest of `@/lib/comments` builds the thread itself: `useComments`, `useCommentCreate`, `useCommentDelete`, `useCommentReactions`, `useCommentComposer`, `useMentionSuggestions` and `useCommentSubscription`.
---
## Editable Settings
Editable settings let builders modify block content through the editor UI (**Content → Settings** tab) without touching code. Always use them for any text, images, icons, colors, or lists that might change between block instances.
Import from `@/lib/editable-settings`.
### `useTextSetting`
Returns a `string`. Use for titles, descriptions, button labels, URLs, etc.
```tsx
import { useTextSetting } from "@/lib/editable-settings";
export default function Block() {
const title = useTextSetting({
name: "title", // unique identifier — changing this resets the value
label: "Title", // shown in the editor UI
initialValue: "Welcome", // starting value
required: false, // optional, default false
});
return
{title}
;
}
```
### `useImageSetting`
Returns `{ src: string; alt: string }`.
```tsx
import { useImageSetting } from "@/lib/editable-settings";
export default function Block() {
const image = useImageSetting({
name: "hero-image",
label: "Hero Image",
initialValue: {
src: "https://images.unsplash.com/photo-...",
alt: "A hero image",
},
});
return ;
}
```
### `useVideoSetting`
Returns `{ src: string }`.
```tsx
import { useVideoSetting } from "@/lib/editable-settings";
export default function Block() {
const video = useVideoSetting({
name: "intro-video",
label: "Intro Video",
initialValue: { src: "https://example.com/video.mp4" },
});
return ;
}
```
### `useVibeCodingBlockIconSetting`
Returns `{ icon: string }` where `icon` is a `lucide-react` icon name. Render it with the `DynamicIcon` component.
```tsx
import { useVibeCodingBlockIconSetting } from "@/lib/editable-settings";
import { DynamicIcon } from "@/components/dynamic-icon";
export default function Block() {
const { icon } = useVibeCodingBlockIconSetting({
name: "feature-icon",
label: "Feature Icon",
initialValue: { icon: "trending-up" },
});
return ;
}
```
### `useNavigationSetting`
Returns one of:
```ts
{
action: "OPEN_URL" | "OPEN_PAGE";
destination: string;
openIn: "SELF" | "TAB" | "MODAL";
modalSize: "SM" | "MD" | "LG" | "XL"; // only used when openIn is "MODAL"
modalType: "POPUP" | "SLIDING"; // only used when openIn is "MODAL"
}
| { action: "OPEN_CHAT"; actionId: string | undefined }
| { action: "TRIGGER_CUSTOM_WORKFLOW"; actionId: string | undefined }
```
The builder picks the action and how it opens. Your code just passes the value to `NavigationAction` or `navigate()`.
`initialValue` sets the starting point, and takes a looser shape than what you get back:
- Link: `{ destination, action?, openIn?, modalSize?, modalType? }`. `action` comes from `destination` — starts with `/` means `OPEN_PAGE`, anything else `OPEN_URL`. `openIn` defaults to `TAB`.
- Chat or workflow: `{ action: "OPEN_CHAT" }` or `{ action: "TRIGGER_CUSTOM_WORKFLOW" }`. The builder picks which action it points at, so there's nothing else to set.
```tsx
import { NavigationAction } from "@/components/navigation-action";
import { Button } from "@/components/ui/button";
import { useNavigationSetting } from "@/lib/editable-settings";
export default function Block() {
const navigation = useNavigationSetting({
name: "cta-navigation",
label: "CTA Navigation",
initialValue: {
action: "OPEN_PAGE",
destination: "/pricing",
openIn: "TAB",
},
});
return (
);
}
```
The `NavigationAction` component also accepts optional `recordId?: string` and `datasourceId?: string` props. When rendering record-specific links/actions, pass both the current record ID and the datasource it belongs to. `datasourceId` is required whenever `recordId` is present — it tells the runtime which datasource the selected record comes from. Also, in the case of a link, it dynamically adds a URL parameter to the final URL `?recordId=`.
```tsx
View details
```
### `useNavigation`
Some things aren't links — a chart segment, a table row, a countdown, a form that just submitted. For those, call `navigate()` from `useNavigation`. It takes the same setting `NavigationAction` takes and opens it the same way, so the builder's choice still applies.
Call it once per block. The setting is an argument, so one `navigate` handles every destination.
```tsx
import { useNavigation, useNavigationSetting } from "@/lib/editable-settings";
import { useRecordCreate, q } from "@/lib/datasource";
import { Button } from "@/components/ui/button";
export default function Block() {
const navigate = useNavigation();
const afterSubmit = useNavigationSetting({
name: "after-submit",
label: "After Submit",
initialValue: { destination: "/thank-you", openIn: "SELF" },
});
const createRecord = useRecordCreate({
fields: q.select({ name: "FIELD_ID1" }),
onSuccess: () => navigate(afterSubmit),
});
return ;
}
```
The second argument takes the same `recordId` and `datasourceId` as `NavigationAction`, for a destination that points at one record:
```tsx
navigate(detailsLink, { recordId: bar.id, datasourceId: "d347bd84-7dc5-4d19-bc98-68417c6ae147" })
}
/>
```
What `navigate()` does, per setting:
| Setting | What happens |
| ------------------------------------------- | ---------------------------------------------------------------- |
| `OPEN_PAGE` / `OPEN_URL`, `openIn: "SELF"` | Navigates the app there |
| `OPEN_PAGE` / `OPEN_URL`, `openIn: "TAB"` | Opens in a new tab |
| `OPEN_PAGE` / `OPEN_URL`, `openIn: "MODAL"` | Opens in a modal, with the builder's `modalSize` and `modalType` |
| `OPEN_CHAT` | Opens the AI chat for that action |
| `TRIGGER_CUSTOM_WORKFLOW` | Runs the workflow with `recordId` and `datasourceId` |
`recordId` gets added to page and URL destinations as `?recordId=`. It's skipped for `#section`, `mailto:`, `tel:` and `sms:` destinations — nowhere to put it.
If the setting points at an action the builder deleted or hid, `navigate()` does nothing. No error, no toast, so don't bother guarding the call.
Use `NavigationAction` whenever a real link will do. An anchor gives you middle-click, "open in new tab" and the browser's hover preview. A click handler loses all three. And don't fall back to `window.open` or `window.location` — those hardcode the destination, so the builder can't change it anymore.
### `useColorSetting`
Returns a CSS color `string`. Use for a color the builder picks — title color, button background, etc. It shows up as a color picker in the Content tab.
`initialValue` is a theme color name or a hex (`"#1A2B3C"`). Default is `"foreground"`. Theme names:
`background`, `foreground`, `card`, `card-foreground`, `popover`, `popover-foreground`, `primary`, `primary-foreground`, `secondary`, `secondary-foreground`, `muted`, `muted-foreground`, `accent`, `accent-foreground`, `destructive`, `border`, `input`, `ring`
```tsx
import { useColorSetting, useTextSetting } from "@/lib/editable-settings";
export default function Block() {
const title = useTextSetting({ name: "title", label: "Title", initialValue: "Welcome" });
const titleColor = useColorSetting({
name: "title-color",
label: "Title Color",
initialValue: "foreground",
});
return (
{title}
);
}
```
A theme name follows the app theme until the builder picks a color. The picker shows the current theme color, and once the builder changes it, a hex is saved.
Pass the value through inline `style`, not a Tailwind class — classes like `text-[...]` are built at compile time and won't pick up the builder's color.
Pick the `initialValue` that matches the element's current look, so nothing changes until the builder edits it: `text-foreground` → `"foreground"`, `bg-primary` → `"primary"`.
### `useArraySetting`
Returns an array of items with a consistent shape. Use for feature lists, team members, FAQs, testimonials, etc.
```tsx
import { useArraySetting } from "@/lib/editable-settings";
import { DynamicIcon } from "@/components/dynamic-icon";
export default function Block() {
const features = useArraySetting({
name: "features",
label: "Features",
schema: {
title: { type: "text", label: "Title", initialValue: "Feature" },
description: { type: "text", label: "Description" },
icon: { type: "vibeCodingBlockIcon", label: "Icon" },
image: { type: "image", label: "Image" },
},
initialValue: [
{
title: "Fast",
description: "Blazing fast performance.",
icon: { icon: "zap" },
image: { src: "", alt: "" },
},
{
title: "Reliable",
description: "99.9% uptime guaranteed.",
icon: { icon: "shield" },
image: { src: "", alt: "" },
},
],
});
return (
{features.map((feature, index) => (
{feature.title}
{feature.description}
))}
);
}
```
### `useBooleanSetting`
Returns a `boolean`. Use for toggles, switches, show/hide elements, etc.
```tsx
import { useBooleanSetting } from "@/lib/editable-settings";
export default function Block() {
const showHeader = useBooleanSetting({
name: "toggleHeader", // unique identifier — changing this resets the value
label: "Toggle header", // shown in the editor UI
initialValue: false, // starting value (default is true)
});
return <>{showHeader && }>;
}
```
**Schema field types:** `"text"`, `"image"`, `"video"`, `"vibeCodingBlockIcon"`, `"color"`
A `"color"` field comes back as a CSS color, same as `useColorSetting`.
**Constraints:**
- Schema cannot contain nested arrays — for list-like text, use a `"text"` field with a separator (e.g. comma) and split it in code
- Do not put a `vibeCodingBlockIcon` field as the **first** field in the schema
- Calling two settings hooks with the same `name` is not allowed
---
## Complete Example — Feature Showcase
A full-featured block combining editable settings, datasource records, and shadcn/ui:
```tsx
import { useTextSetting, useArraySetting } from "@/lib/editable-settings";
import { useRecords, q } from "@/lib/datasource";
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { DynamicIcon } from "@/components/dynamic-icon";
const select = q.select({
name: "$PRODUCT_NAME_FIELD",
category: "$CATEGORY_FIELD",
price: "$PRICE_FIELD",
});
export default function Block() {
// Editable settings for the section header
const heading = useTextSetting({
name: "heading",
label: "Section heading",
initialValue: "Our Products",
});
const subheading = useTextSetting({
name: "subheading",
label: "Section subheading",
initialValue: "Explore our latest offerings",
});
// Live records from datasource
const { data, status, hasNextPage, fetchNextPage, isFetching } = useRecords({
select,
count: 6,
orderBy: q.asc("name"),
});
const items = data?.pages.flatMap(p => p.items) ?? [];
return (
);
}
```
---
## Fetching field options
Use `useFieldOptions` to fetch available options for SELECT or multi-select fields. This is useful for building filters, dropdowns, badges, or any UI that needs to display the available choices from the datasource without hardcoding them. Like the other data hooks, it accepts a `from` alias (`useFieldOptions({ from: ds.orders, select, field })`), required when the block has multiple datasources.
Example to build a filter UI using `useFieldOptions`:
```tsx
import { useState } from "react";
import { q, useRecords, useFieldOptions } from "@/lib/datasource";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
const select = q.select({
title: "$TITLE_FIELD_ID",
productStatus: "$PRODUCT_STATUS_FIELD_ID",
});
export default function Block() {
const [selectedProductStatus, setSelectedProductStatus] = useState(null);
const { options } = useFieldOptions({ select, field: "productStatus" });
const { data, status } = useRecords({
select,
where: selectedProductStatus ? q.text("productStatus").is(selectedProductStatus) : undefined,
count: 10,
});
const items = data?.pages.flatMap((p) => p.items) ?? [];
return (
{status === "pending" &&
Loading...
}
{items.map((item) => (
{item.fields.title}
{item.fields.productStatus?.label || "Unknown"}
))}
);
}
```
---
## Fetching from a REST API
When using a REST API as a datasource, call it with `useProxyFetch` from `@/lib/datasource`. The proxy attaches authentication for you, so don't send tokens, API keys, or auth headers yourself.
`useProxyFetch` returns a function with the same signature as `fetch`. [TanStack Query](https://tanstack.com/query) (or a similar data-fetching library) pairs nicely with it for caching and request state, and we strongly recommend it over fetching inside a `useEffect`.
> **Warning**
>
> **Caveats**: the proxy currently only supports text payloads. Streams, `FormData`, and file uploads won't work.
### Reading data
```tsx
import { useQuery } from "@tanstack/react-query";
import { useProxyFetch } from "@/lib/datasource";
export default function Block() {
const proxyFetch = useProxyFetch();
const { data, status, error } = useQuery({
queryKey: ["products"],
queryFn: async () => {
const res = await proxyFetch("https://api.example.com/products");
if (!res.ok) throw new Error("Failed to fetch products");
return res.json();
},
});
if (status === "pending") return
Loading...
;
if (status === "error") return
{error.message}
;
return (
{data.map((item) => (
{item.name}
))}
);
}
```
### Mutating data
Wrap writes in `useMutation` and invalidate the affected queries on success so the UI refetches:
```tsx
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useProxyFetch } from "@/lib/datasource";
import { toast } from "sonner";
function useCreateProduct() {
const proxyFetch = useProxyFetch();
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (input: { name: string; price: number }) => {
const res = await proxyFetch("https://api.example.com/products", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(input),
});
if (!res.ok) throw new Error("Failed to create product");
return res.json();
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["products"] });
toast.success("Created");
},
});
}
```
### Multiple datasources
When a block has more than one datasource, `useProxyFetch` needs to know which one to route the request to, so pass the datasource alias as its argument. With a single datasource you can call `useProxyFetch()` with no argument; once there's more than one, leaving it out throws an error. Define the aliases with `datasource.define`, the same pattern the record hooks use:
```tsx
import { useQuery } from "@tanstack/react-query";
import { datasource, useProxyFetch } from "@/lib/datasource";
const ds = datasource.define({
store: "ds_id_1",
});
function useProducts() {
const proxyFetch = useProxyFetch(ds.store);
return useQuery({
queryKey: ["products"],
queryFn: async () => {
const res = await proxyFetch("https://api.example.com/products");
if (!res.ok) throw new Error("Failed to fetch products");
return res.json();
},
});
}
```
---
# Action Buttons Overview
Source: https://docs.softr.io/actions/action-buttons-overview
> **Tip**
>
> **Action Buttons** are available to all the subscription plans. Button Visibility options depend on the subscription plan. See [plan comparison](https://www.softr.io/pricing).
**Action Buttons** are buttons that you can add to [List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU), [List Details](https://www.notion.so/19c85b4352da4f79bef36e82d78fc650), [Kanban](https://www.notion.so/3513ac5b44034e1093cf96231dde3997), [Table](https://www.notion.so/92aacbbfe80e41af8f43119403c2ffe7), or [Calendar](https://www.notion.so/cc2a9bc28a5a45a0be6385c5ba1b2dff) blocks to allow your application users to update the [data connected to the block](https://www.notion.so/4230abecf813402aa2926466c313290a), add new data, navigate to other sections in your app, and more. In particular, **Action Buttons** let your users perform all of the [CRUD](https://developer.mozilla.org/en-US/docs/Glossary/CRUD) (Create, Read, Update, Delete) operations on your application’s data.
The **Action Buttons** are available from the **Actions** tab in block settings sidebar and are divided into the following three categories:
1. **Topbar Buttons**. Includes the [Add Record](/actions/ntEfT9zSJk6aY54G6W5KGU/add-record/3LrUMpQY4BKfDDQj6eb8h8) action and the standard **Open Page**, **Open URL**, and **Scroll To** actions that are discussed in greater detail under [on click actions](/actions/ntEfT9zSJk6aY54G6W5KGU/item-on-click-actions/f1ns7phZfNNvgwXA6tTN3M).
2. **Item Buttons.** This category includes actions that can be applied to distinct records in your data such as the [Update Record](/actions/ntEfT9zSJk6aY54G6W5KGU/edit-record/irSJXPF1gCMXNmfsQFscvx), [Delete Record](/actions/ntEfT9zSJk6aY54G6W5KGU/delete-record/peV9LGdJbM9sKHKynqopkH), and [One-click update](/actions/ntEfT9zSJk6aY54G6W5KGU/one-click-update/8BaX5i6KLZhZCrSZERGnej). It includes the standard [on click actions](/actions/ntEfT9zSJk6aY54G6W5KGU/item-on-click-actions/f1ns7phZfNNvgwXA6tTN3M) as well.
3. [Item on Click](/actions/ntEfT9zSJk6aY54G6W5KGU/item-on-click-actions/f1ns7phZfNNvgwXA6tTN3M). In this category, instead of creating a button, you can specify what happens when a user clicks on an item in your data representation.
> **Warning**
>
> Note: You cannot add or edit records located in synced tables.

_Actions tab_
The only exception is the [Kanban](https://www.notion.so/3513ac5b44034e1093cf96231dde3997) block, where there’s also a **Drag and drop** toggle that lets you choose whether you want to allow your users to drag and drop the board items or not.

_Drag and drop toggle on Kanban block_
---
# Add Record
Source: https://docs.softr.io/actions/add-record
## Overview
### Adding the Button
This [action button](/actions/ntEfT9zSJk6aY54G6W5KGU/action-buttons-overview/idg8Fqf2kjFwcx6kyP3jNq) is available under **Topbar Buttons**. It lets users add new records to your data source, such as a [Softr Database](/softr-databases/softr-databases-overview) table. Add record buttons are available on List blocks. To add one, select the List block, open the **Actions** tab, click **+ Add Topbar Button**, and choose **Add Record** from the dropdown.

> **Tip**
>
> By default, your block has one **Add record** button. You can remove it.
### Adding Form Fields
Users need fields to fill in when they add a record. Once you add the button, you can:
1. Give the button a label.
2. Add the fields that users fill in for the new record. Each field has a label, a placeholder, a required switch, and a **Map to** setting that links it to a field in your data source.

### About the Modal
The modal is the form that users see when they add a record. You can set the title of the **Add Record** modal and the text of its Add and Cancel buttons. To see the live form, preview the app or use it live. You can also preview the modal with the eye icon in the upper right of the section. To change the look of the modal (background, text color, button color), use the [Theme](/styling/7qXYEkNvWQamR6vcLXzZnF/application-theme/91YGSL2aDJajXdbPBhitbc) menu tab.

### Setting the On Form Submission
Here you set the success message that users see after they submit the form, and the action that runs next. You can choose:
- **Open new record’s details page:** Sends the user to a details page for the new record. If you have no details page for this type of record, Softr asks you to create one.
- **Close the modal:** Closes the popup and returns the user to the screen they came from.
- **Open a page:** Sends the user to a page in your app.
- **Open an external URL:** Sends the user to a URL you set.

### Button Visibility
After you create the button, click the yellow branching icon to set visibility conditions based on the logged-in user’s [user group](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/user-groups/6XQfKMeKHUvBcAjKvLs3g3).

## Example
Let’s set up this action. We use a [List block](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU) connected to a Tasks table in a [Softr Database](/softr-databases/softr-databases-overview). The list shows the tasks of a product development team. Each task has a **Task** name, a **Status** (the progress of the task), and a **Priority**. The table can have more fields. We want an “Add new task” button so team members can add tasks to the list.

_List of tasks_
First, we set the button label.

_Button label_
Then we customize the other texts of the button. The following gif also shows how to preview the **Add record** pop-up, where users enter the details of a new record.

_Setting up button texts and previewing the modal_
Next, we choose which fields of the data source users fill in. Click **Add field** in the button settings and add each field. A new task needs a **Task** name, a **Status**, and a **Priority**. We add a Text field and map it to the **Task** field of the table. We add two dropdown fields and map them to **Status** and **Priority**, because both are select fields in the table.

_Adding fields for the add new task functionality_
> **Info**
>
> You can also add a [Signature field](/displaying-and-creating-data/vikC2AWEpQGkZd4jGyoVxo/layout-customizable-form/jCim5VWZePgZuaRsUZBnpG#signature-field) to capture eSignatures when users add records.
> **Warning**
>
> Computed fields, such as formula, lookup, and rollup fields, don’t appear in the list of mappable fields for the form.
> **Warning**
>
> You can’t add or edit records in synced tables.
Now we define who can see and use the button (see [button visibility](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/action-button-visibility/tqpb8TkUD4U4DCAUA2hjKo)).
> **Tip**
>
> Button visibility options depend on the subscription plan:
>
> → On Free and Starter plans you can decide who can see the button (All Users, Logged-in Users, or Non Logged-in Users)
>
> → On the Professional plan you can also configure conditional visibility, but you can’t set [custom user groups](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/user-groups/6XQfKMeKHUvBcAjKvLs3g3).
>
> → On the Business plan you have access to all the features in Button Visibility.
> See [plan comparison](https://www.softr.io/pricing).
The users of our task list are the team members who work on those tasks. Their emails are in the **Assignee email** field of the Tasks table, next to each task.

_The Tasks table in a Softr Database: each task has a status and an assignee email._
> **Tip**
>
> Users who sign in to your app must exist as [users in Softr](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/users-menu/5JTzjtbvp8Skemd26A9ho9). If your users live in another data source, see [Syncing users with a data source](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/syncing-users-with-a-data-source/hshRGygHr4T33EnaLntGf9).
We also create a [user group](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/user-groups/6XQfKMeKHUvBcAjKvLs3g3) for project managers only.

_Creating a user group for project managers._
Next, we set the button visibility so that only the **Project Managers** user group can see the button.

_Setting button visibility_
Now let’s test the setup from the user’s side.
### Testing adding new tasks
To test the setup, we sign in to the app as a project manager and add a new task to the list. The following gif shows it.

_Adding a new task_
---
# Edit Record
Source: https://docs.softr.io/actions/edit-record
This [Action Button](/actions/ntEfT9zSJk6aY54G6W5KGU/action-buttons-overview/idg8Fqf2kjFwcx6kyP3jNq) lets you update records in your [data source](https://www.notion.so/4230abecf813402aa2926466c313290a).
> **Tip**
>
> By default, you’ll have one **Edit** button added to your items, which you can remove if needed.
To demonstrate how the **Edit Record** button works, we’re going to use a [List block](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU) connected to an [Airtable](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX) data source, which shows a list of tasks for a hypothetical product development team and has three fields: **Name** (the name of the task), **Assignee** (who it is assigned to), and **Status** (the current progress status of the task). We want to enable an “Update task status” button to allow each development team member to update the status of **his/her own task**.

_List of tasks_
First, we are going to configure the button label.

_Button label_
Then, we are going to customize the labels and messages that are going to be displayed on the pop-up that the users are going to use to perform the update.

_Customizing pop-up labels_
Next, we need to specify which fields from our data are going to be available for update. **By default, all the fields present in the connected data source are going to be added automatically.** So, let’s remove the ones that we don’t need and leave **Status** only. As you can see in the following gif, the [field is already mapped](/actions/ntEfT9zSJk6aY54G6W5KGU/mapping-fields-for-actions/7ukkeMfqspmniU4MQyTiV3) to its corresponding field on Airtable, so we don’t need to do anything else there. We’ll just add a label.

_Configuring connected fields_
> **Warning**
>
> Note that [computed fields](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX#airtable-computed-fields) will not appear in the list of mappable fields for the form.
> **Warning**
>
> You cannot add or edit records located in synced tables.
## Button Visibility
Now, let’s configure the [button visibility](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/action-button-visibility/tqpb8TkUD4U4DCAUA2hjKo) to specify who exactly can see and thus use the button. The users of our task list are the same people who are working on those tasks, so we are going to [connect the same Airtable base](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/syncing-users-with-a-data-source/hshRGygHr4T33EnaLntGf9) with tasks and assignees to Softr as a user database.

_Airtable table with the list of tasks and assignees._
> **Tip**
>
> The users sync between Softr and data source is one-way (from Softr to data source), so, if you connect a data source with users without having them [in Softr](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/users-menu/5JTzjtbvp8Skemd26A9ho9) first, you’ll need to create the same users in Softr as well to establish the connection.
Now, let’s configure the actual button visibility settings. The users need to be able to update their own tasks only, so we’re going to set a [conditional visibility rule](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/action-button-visibility/tqpb8TkUD4U4DCAUA2hjKo) according to which the user sees the update button only on the tasks that have his/her email in the **Assignee** **Email** field.

_Configuring visibility rules_
That’s it. The last step is to make sure everything’s working as expected.
## Testing task status update
To test our setup, we are going to log into our application with one of the application users and update her task status. The following gif illustrates that.

_User updating her task status_
---
# One-click update
Source: https://docs.softr.io/actions/one-click-update
## Using the One-click Update Action
This [Action Button](/actions/ntEfT9zSJk6aY54G6W5KGU/action-buttons-overview/idg8Fqf2kjFwcx6kyP3jNq), similar to the [Edit Record](/actions/ntEfT9zSJk6aY54G6W5KGU/edit-record/irSJXPF1gCMXNmfsQFscvx) button, lets your users update records (e.g. [List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU) items) in your data. The difference is that, instead of letting the user input data or choose an option, you predefine the value that needs to be applied. Thus, the user only needs to click the button to complete the update.
To set up the button, you need to specify the field (**Field** parameter) that needs to be modified and set the value that will replace the existing value of the field.
There are two ways to use the One-click update action. You can either **Replace a Value** or **Clear a Value**.
- **Replace existing value** - This option will let you set a field value in your datasource, replacing anything already in that field. Selecting this will expose another field where you can select what to replace the value with. You can use a static value, or pick a dynamic value such as Logged in user data, current record data, or even datetime values and URL parameters.
- **Clear value** - This option lets you reset a field in your datasource back to empty, 0, or null, depending on the field type.

_One-click update setup_
**The Replace existing value with settings are similar to those of the** [**hidden field values**](/actions/ntEfT9zSJk6aY54G6W5KGU/mapping-fields-for-actions/7ukkeMfqspmniU4MQyTiV3).
Let’s consider an example to see this functionality in action.
## Example: Letting a development team users reassign tasks
Let’s say we have a list of tasks for a development team, where each task has an assignee (**Assignee Email** field).

_List of tasks_
We are going to add a One-click update button to list items named “Reassign to me,” which will let each user reassign the task to him/her with one click.

_Adding the button to items_
Next, we need to add a field to the button, map it to the **Assignee Email** field, and select the **Logged-in user’s Email** as the value.
> **Warning**
>
> Note that [computed fields](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX#airtable-computed-fields) will not appear in the list of mappable fields for the form.
> **Warning**
>
> You cannot add or edit records located in synced tables.

That’s it. Now, let’s log in with one of the development team users and test how this works.

_Testing the setup_
---
# Delete Record
Source: https://docs.softr.io/actions/delete-record
This [Action Button](/actions/ntEfT9zSJk6aY54G6W5KGU/action-buttons-overview/idg8Fqf2kjFwcx6kyP3jNq) lets you delete records in your [data source](https://www.notion.so/4230abecf813402aa2926466c313290a). To demonstrate how the **Delete Record** button works, we’re going to use a [List block](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU) connected to an [Airtable](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX) data source, which shows a list of tasks for a hypothetical product development team and has three fields: **Name** (the name of the task), **Assignee** (who it is assigned to), and **Status** (the current progress status of the task). We want to enable a “Delete task status” button to allow project managers to delete tasks.

_List of tasks_
First, we are going to configure the button label and that texts that are going to be shown in the pop-up (or modal) opened by the delete button.

_Configuring button and modal labels and other texts_
## Button Visibility
Now, let’s configure the [button visibility](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/action-button-visibility/tqpb8TkUD4U4DCAUA2hjKo) to specify who the button is going to be visible to. The users of our task list are the same people who are working on those tasks, so we are going to [connect the same Airtable base](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/syncing-users-with-a-data-source/hshRGygHr4T33EnaLntGf9) with tasks and assignees to Softr as a user database.

_Airtable table with the list of tasks and assignees._
> **Tip**
>
> The users sync between Softr and data source is one-way (from Softr to data source), so, if you connect a data source with users without having them [in Softr](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/users-menu/5JTzjtbvp8Skemd26A9ho9) first, you’ll need to create the same users in Softr as well to establish the connection.
Now, let’s configure the actual button visibility settings. We need to allow only Project Managers to delete tasks, so, first of all, we need to create a [User Group](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/user-groups/6XQfKMeKHUvBcAjKvLs3g3) that includes only the users whose **Position** is **Project Manager**.

_Creating a user group for project managers_
Next, we need to navigate to our delete button’s visibility settings and select the user group that is going to be able to view the button.

_Setting button visibility_
That’s it. The next and last step is to make sure everything’s working as expected.
> **Tip**
>
> In **Button Visibility** settings, apart from selecting user groups under **WHO CAN SEE**, you can also set conditional visibility under **ON WHICH RECORDS.** This works similar to [list conditional filters](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/conditional-filters/mDnn7jnpPiYmJcT99jpt7m).
## Testing task deletion
To test our setup, we are going to log into our application with a user whose position is Project Manager and attempt to delete one of the tasks. The following gif illustrates that.

_Deleting a task_
---
# Call API
Source: https://docs.softr.io/actions/call-api
## What can I do with the Call API action?
> **Note**
>
> Call API action is available for users on the [Professional plan and above](https://www.softr.io/pricing).
Buttons can trigger an action to send a POST, PUT, PATCH, or DELETE request to any REST API or webhook endpoint, allowing you to interface directly with external services and tools. It allows you to integrate with services that Softr does not natively provide an integration for. Simply put, you can do just about anything you can imagine - without needing additional automation or workflow tools!
**Do things like:**
- Click on an Invoice record in Softr app → Create an invoice in Stripe to the associated client
- Click on a Lead record in Softr → Update the status in Pipedrive or Salesforce
- Click on a File record Softr → Attach the record URL of the associated client project in tools like Clickup, Monday, Asana, Notion, or Coda
- Click on an Customer request record in Softr app → Send a notification to Slack or send an email
- Click on an Inventory record in Softr app → call API automations or workflows in automation softwares like Zapier, Make, Triggre, n8n, and more.
- Click on a Support Ticket record in Softr → Update the ticket in Jira
## Where can I use it?
The Call API action is available for use in two locations:
- **List Blocks** - Call API is available on buttons added to list items (not topbar buttons)
- **List Details Blocks** - Call API is available on buttons added to list details blocks
## How do I use it?
The Call API actions can be broken down into 4 main sections:
1. Webhook or Base URL
2. Request Method
3. Parameters
4. Success Message

**Let’s look at each in a bit more detail.**
> **Tip**
>
> Tip: Since every webhook and API is different, what you place in these fields can be found in the individual service’s or tool’s documentation. You can usually find it by performing a web search for “developer docs for \_\_\_\_\_\_\_”.
>
> **Softr does not provide documentation for services you want to use in this trigger**.
### 1. Webhook URL
In this field you will put the webhook URL or API endpoint URL you would like to send the request to. The URL you use will depend on the service you are using to receive the data. All URLs should begin with `https://` and act as one-way “doors” that you need to “knock on” or “call” in order to do or see different things with the service you’re integrating with. Some doors are locked though, as we will see in point number 3.
### 2. Request Method
In this dropdown you have 4 options to choose from, depending on what the webhook or API requires as a part of its service. Using the door analogy, different doors have different methods for operating them - some have knobs, some have levers, some push or pull to open. In the same way, webhook and API URLs can have different methods for calling them and we can use the POST, PUT, PATCH, and DELETE methods in this dropdown to tell an endpoint what we want to do with it. The differences in how these methods are used can vary, but for simplicity sake here’s a general break down of how they are used for most webhooks and APIs:
- **POST** - Typically used to create new data with an endpoint or perform a new action
- **PUT** - Typically used to update and replace all data
- **PATCH** - Typically used to update and replace only the data specified in the call
- **DELETE** - Used to delete the entirety of a record or data
### 3. Parameters
The parameters section offers three ways to add what are called key/value pairs to the webhook or API call. You can think of these key/value pairs as the information should be sent in the request. If the URL and Method is the door and the way the door operates, then key/value pairs are what pass through the door. As mentioned in point number 1, some doors are locked and require a key.
In the same way, some webhook or API URLs may require an API Key or password to access them, which you can often send using Query Parameters or the Header. Different webhooks and APIs will require different combinations of these to be toggled on or off, but turning any of them on reveals two fields that you can use to define both the key and the value of the key. You can add as many of these as are required by the tool or service. You can also use any combination of static data or logged-in user and current record data in the “Value” dropdown. This allows you to send any app data as a part of the call.

**Let’s look at the three types of key/value pairs you can add:**
- URL Parameter - this type of key/value pair is appended to the end of the Webhook URL when the call is performed and is very flexible in how it can be used, whether sending simple information or even API Keys to access an endpoint
- Header Parameter - this key/value pair is often used to authenticate the request with an API Key or send information about the type of content you’re sending.
- Body - key/value pairs placed in the body are typically the important content you’re actually wanting to send and use elsewhere such as emails, names, numbers, or lists of other items
The great thing about webhook calls in Softr is that we take care of all the formatting for you, so you never need to worry about JSON structures or missing a comma in the code. To delete a key value pair, just click the trashcan to the right of it.
### 4. Success Message
Much like forms and editing list items, you can set a success message that is shown to the app user, after the webhook or API call has been completed.
## Advanced Capabilities
### Webhook/API Event Listeners
You can use custom code in the header or footer of a page along with an event listener to monitor the server’s response to a webhook or API call:
`call-api-success` event with field values is triggered after getting response with a success status code.
`call-api-failure` event is triggered after getting response with error code.
Example:
```javascript
```
---
# Download File
Source: https://docs.softr.io/actions/download-file
## What can it do?
Let your users download a file attached to an item in a list or on a list details block. Previously you could do this using the “File” field in a list or list details’ Item Fields section, however now you can also let users do this through a button as well.
## How do I use it?
First, you’ll need to make sure you have an attachment field or a public URL in your datasource that holds the file you want to download. Click on the list or list block that you want users to download from. Then:
1. Click on the Action tab in the topbar of the block’s settings panel
2. Click **Add Item Button**
3. Scroll down in the list of action options to find and click **Download File**

In the settings for the action, you have several things to setup as well:
1. Customize what the button label says
2. Choose the field in your datasource that holds the URL or attachment that the user should be able to download.
3. Customize the message that is displayed to the user when the download is completed.

---
# Mapping Fields for Actions
Source: https://docs.softr.io/actions/mapping-fields-for-actions
When you add an **Action Button** like **Add record** or **Update record** to a block, Softr needs to know which columns in your data source the button should write to. That pairing — a form field in Softr linked to a column in your table — is called a **field mapping**.
> **Success**
>
> Softr now handles most of this for you automatically. As soon as you pick an action, every mappable field from your data source shows up pre-configured. You only need to step in when you want to customize a field, remove one, or collect a value behind the scenes (a **hidden input**).

_When you add an Add record action, Softr auto-maps every eligible column from the connected table. Computed (formula) fields are skipped because they can't be written to._
## How to add an action button
Open any block that supports actions — lists, tables, grids, item details — then:
1. **Select the block**
Click the block on the canvas to open its settings panel on the right.
2. **Open the Actions tab**
In the right-hand settings panel, switch to the **Actions** tab.
3. **Add a button**
Click **+ Add topbar button** (applies to the whole block, like "Add a new project") or **+ Add item button** (applies per row, like an Edit button on each card).
4. **Choose the action type**
Pick from the dropdown — options listed below.

**Add record**
Creates a new row in a connected table. The most common starting point — field mapping matters a lot here.
**Update record**
Edits an existing row. Only available as an item button. Same field-mapping UI as Add record.
**Run custom workflow**
Triggers a Softr workflow. Useful when you need to combine values from multiple sources before writing.
**Open page**
Navigates to another page in your app.
**Open URL**
Opens an external URL in a new tab.
**Scroll to**
Smoothly scrolls to another block on the same page.
**Ask AI**
Opens an AI chat scoped to the current record or context.
> **Info**
>
> For this guide we'll focus on **Add record** and **Update record** — those are the action types where field mapping applies.
## What auto-mapping does (and what you still control)
As soon as you pick Add record or Update record, Softr scans the connected table and creates a field entry for every writable column, with the correct **Input type** already selected (Text, Long text, Number, Dropdown, Date, Attachment, and so on).
**Computed / formula fields are skipped**
They're read-only in the data source, so they can't be written to from an action.
**Lookup and linked-record fields are included**
They show up as dropdowns or multi-selects, depending on how the underlying table is configured.
**You can remove any field you don't want users to fill in**
Hover the field row and click the trash icon. Removed fields won't appear in the form.
**You can re-add a field later**
Click **+ Add field** at the bottom of the list. This also lets you add a field that isn't yet bound to a column — useful for hidden inputs (see below).

> **Tip**
>
> The header of each field row shows the **field's label** on the left and the **column type** on the right (e.g. "Status — Dropdown"). A field that's missing its mapping will show **"Not set"** — that's the one indicator to watch for.
## Configuring an individual field
Click any field in the list to open its configuration popover.

The popover has the following controls, top to bottom:
- **Field header** — shows the column currently mapped to this input. Click the dropdown to remap it to a different column in the same table.
- **Hidden input** _(toggle)_ — when off, the field shows in the form for the end user to fill in. When on, the field is collected silently — see the [Hidden inputs](#hidden-inputs) section.
- **Input type** — usually set correctly by auto-mapping. Override it only if you want a different UI (e.g. render a Text column as an email input with validation).
- **Required** — forces the user to fill the field before the form can submit. For Add record, this corresponds to a required column in the data source; for Update record, it guards against accidental blanks.
- **Label** — the text shown above the input. Defaults to the column name.
- **Tooltip** — a small "?" next to the label with helper text on hover.
- **Placeholder** — ghost text inside an empty input.
- **Hint** — helper text shown below the input.
- **Default value** — prefills the input. For Add record, this is the value used if the user doesn't change anything. For Update record, this is overridden by the existing record value.
- **Validation** — expands to show input-type–specific rules (min/max length, regex pattern, minimum date, file size, and so on).
## Hidden inputs
A **hidden input** is a form field the end user never sees — it's submitted automatically with a value you pick. These are great for automatically saving values to a record without requiring input from the user. For example, you may want to automatically assign the Project Lead as the Logged in User, since the Logged in User is the one creating the new Project record.
> **Info**
>
> **Change from the old UI.** Hidden fields used to live in a separate section at the bottom of the action settings. They're now a **per-field toggle**, which means any field in your form — whether Softr auto-mapped it or you added it yourself — can be turned into a hidden input with one click.
To make a field hidden:
1. **Open the field**
Click the field to open its configuration popover.
2. **Turn on Hidden input**
Flip the **Hidden input** toggle.
3. **Pick a value source**
Choose what to submit from the **Value** dropdown.

The Value dropdown gives you **six categories** of automatically-collected values. Each is covered below.
### Logged-in user
Pulls any field from the signed-in user's record in your users table.

The list shows **every column in your users table**, not just a few built-ins. Common picks:
- **Email** or **Name** — to stamp a submission with who created it.
- **Client company** or **Client contact of** (in Client Portal apps) — to tie a new record to the logged-in user's organization.
- **Record ID** — to link the new record to the user's row via a linked-record field.
> **Note**
>
> **Migrating from the old UI?** You no longer need the `{LOGGED_IN_USER:'Field name'}` custom-value syntax for this. The Logged-in user submenu covers any field directly.
### Details page record
Available on pages that have a parent record (list-detail pages, Users-scoped pages). Works the same as Logged-in user — you get a submenu of every field on the parent record.

> **Tip**
>
> **Clearest use case:** an Add record button on a "Project detail" page that creates a Task. Pick **Details page record → Record ID**, map it to the Task's **Project** lookup column, and every new task is automatically linked to the project the user is viewing.
### URL parameter
Collects a query-string parameter from the page the button is on. Enter the parameter's name.

**Example:** a job board where each page URL is `yoursite.com/job-details/senior-product-manager?recordId=rec7HcXAgKmlk8inf`. Setting the Value to URL parameter → `recordId` captures `rec7HcXAgKmlk8inf` and stamps it onto the submission.
### Page URL
Captures the full URL of the current page, including query string. Useful when the same action button lives on multiple pages and you want to know which one was used.
### Current time
Records a timestamp at the moment of submission. You can pick the format (ISO datetime, date only, Unix timestamp) from the submenu.

> **Warning**
>
> Because Softr stamps this on submit, it's the correct way to populate a "Created at" or "Last edited" column — don't try to compute it client-side, as client clocks can be wrong.
### Custom value
A free-text box where you can type any literal value — static text, a fixed tag, a number, a default value. Keep in mind that the value type should match the field type its being mapped to. For example, don't send a string (letters and symbols) to a pure number field.

Useful for:
- Tagging all submissions from a specific page (_"Source: marketing-landing"_).
- Filling a default category that the user shouldn't change.
- Pulling anything you can express as a literal value.
## Update record: what changes
Update record uses the same field-mapping UI as Add record — all the auto-mapping, per-field configuration, and hidden-input behavior work identically. The main differences are operational:
**Item buttons only**
Update record is only available as an **item button** (per row), because it needs an existing record to operate on.
**Form pre-fills**
The form pre-fills with the current row's values. **Default value** in the field config is ignored if the record already has a value.
**Hidden inputs still overwrite**
Stamp a `Last edited at` column with Current time on every update and that's exactly what happens.
**Wiring is identical**
Click the block → **Actions** tab → **+ Add item button** → **Update record** → tweak fields as needed.
## FAQ
**Auto-mapping added a field I don't want my users to fill in. Can I hide it?**
Yes — two options. If the field should be invisible but still written to with a value you control, leave it in the list and turn on **Hidden input**. If it shouldn't be touched at all on this action, hover the field row and click the trash icon to remove it.
**One of my columns didn't show up in the auto-mapped list. What's going on?**
The most common reason is that the column is a **computed / formula field** — those are read-only in the source, so Softr skips them. Other possibilities: the column has an unsupported type for the block's data source connector, or it was added to the table after the block was configured.
Open the **Source** tab and click the refresh icon next to the Database/Table selector to re-sync the schema.
**I'm using the `{LOGGED_IN_USER:'Field` name'} syntax in an older doc. Does it still work?**
Yes, that syntax is still supported for backwards compatibility — you'll find it under **Custom value**. But for new work, use the **Logged-in user** submenu instead. It's type-safe, it updates if you rename the column, and it handles escaping correctly.
**Do hidden inputs run Validation rules?**
Yes. Validation applies to all fields, hidden or not — the system treats a hidden input the same as any other submission. If a hidden input's value can't satisfy a required rule or a regex pattern, the submission will fail.
That's worth knowing when you combine hidden inputs with strict validation (e.g. a hidden `recordId` field with a regex that matches Airtable record-ID format).
**Can I compute a hidden value from multiple sources (e.g. "user email + current time")?**
Not directly in a single field. Each hidden input collects one value from one source. For combinations, either:
- Use a **custom workflow** action, which lets you build a payload from multiple values before writing, or
- Rely on a **formula field** in your data source that computes the combination after insertion.
---
_Last updated: April 2026. If something in this doc looks wrong or out of date, please let our support team know\._
---
# Item on Click Actions
Source: https://docs.softr.io/actions/item-on-click-actions
This category in the **Actions** tab of block settings lets you specify what happens when a user clicks on an item in your data representation ([List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU), [Calendar](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/calendar/rdfXqxaPkTFioEbjBBAZai), and other blocks).
Apart from the default **Do Nothing** option, there are the following three options:
- **Open Page**. Opens another page within your Softr app.
- **Open Url**. Opens any given Url.
- **Scroll To**. Scrolls to a specific section on the same or on any other page.

_“Item on click” options_
The following gif illustrates how that works from the user’s perspective.

_Opening a page on click_
## Open in
Further on, when you select one of these options, an **Open in** dropdown will appear below, where you can specify if the new destination should open in the **Same Tab**, in a **New Tab**, or inside a **Modal** (not available for the **Scroll to** option).

_“Open in” dropdown_
The **Modal** option has some additional settings, so let’s check those out.
### Modal

_Modal settings_
A modal is basically a pop-up that opens on the same page the user’s on. It has two types: **Centered** and **Sliding**.
The **Centered** **modal** opens a pop-up in the center of the page, and you can also select a **size** for it.

_Centered modal_
The **Sliding modal** open a sidebar from the right side of the page.

_Sliding modal_
---
# Export
Source: https://docs.softr.io/actions/export
## Export PDF
On certain newer list details blocks you can add a button to Export the block itself or even the entire page.
> **Warning**
>
> Currently the Export PDF action is only available on the new “Item Details” block.
To add an Export PDF action, add a button to your Item Details block, then click on Export as the button action. Then set the default file name and whether you want to export just the block or the entire page.

_Add a button to an Item Details block with an Export action_
## Export or Download CSV or XLSX
On the Table block, you can export the table data as either a CSV file or an Excel spreadsheet file. On a table block, add a topbar button and choose Download as the action type. For more info, see our article on the [Table Block](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/table-block-/j7rGwu7J7zuU69h3bZ7HFe).

_Add a topbard button on a Table block and set the action to Download._
---
# Ask AI
Source: https://docs.softr.io/actions/ask-ai
## Overview
Ask AI is Softr's built-in chat assistant that acts like a real-time analyst, reading your live app data and answering questions instantly. Unlike other AI tools that give vague answers or require complex setup, Ask AI is embedded directly into your Softr apps with no API keys. All you need to do is toggle it on!
Here are some key features:
🔍 **Reads from your app data**
- Pulls from live data inside dynamic blocks in your Softr apps
- Gives real-time answers based on your current data
🛡️ **Secure by default**
- Respects your app's permissions and visibility rules
- Users only see data they're authorized to access (no accidental data exposure)
⚡ **No setup required**
- Built directly into your Softr application—just toggle it on at the block level
- No API keys or complex configurations needed
## How to Add Ask AI to Your App
**Step 1:** In the Softr Studio, navigate to your dynamic block's **Actions** section

**Step 2:** Select **Add Topbar** button and choose Ask AI from the options.

**Step 3:** From here, you can adjust the label and icon, and use the dropdown to customize messages, instructions, response style, suggested prompts, and appearance.

**Step 4:** Publish your app. The chat interface will now be available to your users (depending on block permissions)


## Security & Permissions
Ask AI only analyzes the data a user is allowed to see at the block level, always respecting your app's permissions and visibility settings.
You can decide who sees the Ask AI button—like showing it to managers but hiding it from clients. And when users ask questions, Ask AI only analyzes the data they're allowed to see, including filtered views (like "tasks assigned to me").
## Requirements & Limitations
✅ **Supported**
- Dynamic blocks (e.g. Tables, Lists), and Vibe coding block connected to any of Softr's supported data sources (except REST API)
❌ **Not Supported**
- Static blocks or blocks connected to REST API data sources
- Ask AI is currently only available at the block level to ensure secure, permissioned responses.
- App-wide Ask AI implementation is coming soon!
### AI Credits
Ask AI is available on all plans, including free. Every query directed to Ask AI consumes AI credits based on the complexity of the response and the amount of data analyzed. Each query counts toward your workspace's total monthly credit usage.
## FAQ
**Can I use Ask AI on the free plan?**
Yes. Every Softr plan (including Free) comes with a set amount of monthly AI credits to use toward Ask AI and other AI features. If you run out of AI credits in a given month, your Ask AI will pause until your credits reset with your plan or you purchase a credit add-on. [Learn more about AI credits](/workspace-and-billing/jZP6yaeXMiJCuB6HhS4xKd/ai-credits/5VRMhf7Q6xvy7AJqyiQLx5).
---
# Add users to a Softr app
Source: https://docs.softr.io/add-and-manage-users/add-users-to-a-softr-app
## Create users
You can add users to a Softr app in many different ways:
- Create a public [signup form](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/signup-form/tPe3uxmdcUNeFYuaLTR1o9)
- [Add users manually in Users tab](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/add-or-import-users-manually/g5R1bGnBTFJ3sWLR8Mgdng)
- [Sync with an external data source](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/syncing-users-with-a-data-source/hshRGygHr4T33EnaLntGf9)
- Create users via [Zapier](https://zapier.com/apps/softr/integrations) or API
Depending on the application, one option might be preferable to the others. For instance:
- If you're building a member community that anyone can join, you’d want to have a public signup page.
- If you run an [internal tool](https://www.softr.io/internal-tool) for your company, you’d want to add users manually.
## Sign-in (authentication) methods
You can let users sign in to a Softr app using any of the following methods.
> **Tip**
>
> Avoid mixing multiple sign-in methods within the same application.
### Sign in with email & password
The most standard option. Users can log into an app using their email and password.
### **Sign in with email code**
[This option](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/signin-with-email-code/5Ab4ZFWG788NHL2AB6zt2f) lets your users enter their email and get a one-time code to access your app.
### Sign in with m**agic Link**
Magic link is a URL with a unique token that will allow a user to log in by simply clicking on the link or entering it in the browser address bar.
### Sign in with Google
Allow users to sign in with Google.
### **SAML Single Sign-On**
SAML is an open standard that allows different third-party services (Identity Providers) to pass authorization credentials to service providers (including your Softr app), so that users can use a single set of credentials to log into different service providers. You can learn more about single sign-on and how to set it up for your Softr app [here](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/saml-single-sign-on/j9hELMUfGtAGqoNzejgoif).
### **OpenID Single Sign-On**
[OpenID Connect (OIDC)](https://openid.net/connect/) is an open authentication protocol that extends the [OAuth 2.0](https://oauth.net/2/) protocol, adding an identity layer to it. OpenId is utilized by numerous services, and Softr currently supports the [Outseta](https://www.outseta.com/) membership software (**more options available soon**). [Here](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/openid-single-sign-on/hqqStep7RUmiSMb6qnGLkq), you can learn how to integrate Outseta with Softr to allow your users log into your Softr app with their Outseta credentials.
---
# Users Menu
Source: https://docs.softr.io/add-and-manage-users/users-menu
The **Users menu** can be accessed from the top toolbar inside of Softr Studio. Click on the Users tab to see a list of users that exist in your application.

## Sync users with a data source
You can manage users entirely in Softr or [sync users with an external data source](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/syncing-users-with-a-data-source/hshRGygHr4T33EnaLntGf9). By connecting to an external data source, you get to use additional custom fields to create user groups and application logic.
> **Tip**
>
> The **Last Seen Date** data is available to **Professional, Business, and Enterprise plan** users only. This field is updated once per hour.
## User Properties
By default the Users tab will have some columns to display information about your users. If you have other properties about your users from your synced data source, those will not be shown here, but will still be available to use inside your app for filtering, user group creation, etc. Here are the fields available in the Users tab:
- **Email (required)**: This field stores the email of your users and is required for us to create user login functionality.
- **Name**: This field stores the full name of your users and is totally optional, but we highly recommend it to create a personalize experience for your users. Softr can automatically parse this into first and last name for email notifications and other uses.
- **Created Time**: This is the date and time that the user was created _**in Softr**_, not in your data source.
- **Last Seen Time**: This field is available on Professional plans and higher. It shows the last date and time a user last logged in and is updated every hour.
- **Synced:** Shows whether a user is being synced as an app user, thus counting towards your app user limit denoted by [your plan](https://www.softr.io/pricing).
- **Status**: Shows whether a user has been invited to the app, not invited to the app, or activated. This has no bearing on the sync status of the user, but can be affected by whether a user is synced or not. For instance, a user who is not synced cannot also be invited or activated.
- Not invited: A user has not been sent an invitation to join the app and also has not joined themselves
- Invited: A user has been sent an invitation to the app, but has not signed up or logged in.
- Activated: A user has either signed up or logged in to the app at least once.
- **User Groups**: This shows the user groups that a person is a part of. If you experience slow updating of these user groups, you can try turning off [user caching](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/advanced-settings/3aBby3An1TAPWnFTWc8TwS#user-caching). This UI is a bit behind actual updates so if you don’t notice an immediate change here, it is likely still functioning correctly in the end application.
- **Creation Method**: Shows how a user was created. The options are:
- Manual: Created manually by you in the Softr UI or by CSV import.
- Self-sign up: The user signed up to the app themselves.
- Source: The user was imported by syncing with a data source.
- **Authentication Method**: Shows how the user authenticated (logs in) to the app.
- Google: The user signed up/logs in using Google Sign-in.
- Email/Password: The user signed up/logs in using just Email and Password or One time codes.
- SAML/OpenID: The user signed up/logs in using SSO.
- **Magic Link**: If Magic Link is turned on in your [Authentication](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/user-authentication/7gJmq6B7syYE3hRoFxLs5J) settings, the users [magic link](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/users-tab/5JTzjtbvp8Skemd26A9ho9#manage-magic-link) will appear in this field.
## Add user(s)
You can [add users manually](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/add-or-import-users-manually/g5R1bGnBTFJ3sWLR8Mgdng) by clicking on the Add user(s) button. Adding users directly to Softr will also create them in your connected datasource. Softr will prompt you to send them an optional invitation email as well.

## Managing users
By selecting users you want to manage, you will be presented with a list of actions:
- Generate a [magic link](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/users-tab/5JTzjtbvp8Skemd26A9ho9#manage-magic-link) for the selected users.
- Resend invite emails to the selected users.
- Download the user list as a CSV file.
- Delete the selected users.

> **Tip**
>
> Please, note that **deleting** a user entry from your Softr app's Users section will delete it in the **connected data source too**.
## Manage magic link
With **Magic Link**, you can generate a unique token for your users to log into your Softr app without manually signing in with a password. This can be handy when you create a user in the **Users** section and need them to sign in for the first time. Later on, the user can set up the account info in **User Profile** and sign in the usual way.
Let's see how that works.
### **Generating magic link**
First, you need to select the users you want to generate the link for (using the checkboxes in the first column).
After selecting the users, click **Generate Magic Links** under the **Actions** menu.

_Generate magic link_
### **Copy magic link**
After generating the link, you can copy it using the copy button.

_Copying the link_
### **Regenerate magic link**
You can regenerate any user's **Magic Link** at any time using the regenerate button as shown below.

_Regenerating the link_
### Delete a Magic Link
You can also revoke/delete a magic link by clicking on the trash can icon:

_Delete a magic link using the trash can icon_
### Use magic link
That's it, now you can send the link to the user you've generated it for. As soon as the user click's on the link or pastes it in the browser address bar, he/she will access your site in logged-in state.
> **Tip**
>
> If you want the user to be taken to a specific page in your application, you can append the following parameter at the end of your magic link: **`&next-page=/page-path`**
>
> For instance, if you have a `yourdomain.com/about-us` page that you want to add, your parameter will look as follows: **`&next-page=/about-us`**
>
> You can also append entire URLs as the `next-page` value like `https://yourdomain.com/details?recordId=XXXX` to “deep link” someone to a specific record after logging in.
---
# Syncing users with a data source
Source: https://docs.softr.io/add-and-manage-users/syncing-users-with-a-data-source
You can manage your users entirely in Softr or sync users with an external [data source](/4230abecf813402aa2926466c313290a?pvs=25). By connecting to a data source, you get to use additional custom fields to create [User Groups](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/user-groups/6XQfKMeKHUvBcAjKvLs3g3) and application logic (e.g. [Conditional Filters](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/conditional-filters/mDnn7jnpPiYmJcT99jpt7m)).
## 2-way sync availability per source
| | |
| --------------- | ---------------- |
| **Source** | **Availability** |
| Softr Databases | ✅ |
| Airtable | ✅ |
| Google Sheets | ✅ |
| ClickUp | ✅ |
| Coda | ✅ |
| SmartSuite | ✅ |
| SQL | ✅ |
| Monday | ✅ |
| HubSpot | ✅ |
| Notion | ✅ |
| Supabase | ✅ |
| Xano | ✅ |
| BigQuery | N/A |
| REST API | N/A |
## Setup
### Making the Connection
Click on the Users menu panel, then click on the **Sync with data source** button to start the setup. You will notice that a test user is already created for you manually, but you can delete this user before syncing to a data source.

Next, you need to select the data source you want to map to. Softr offers a variety of datasources to pull User’s from, and each one has its own connection methods. Learn more about data source connections [here](/data-sources/1YYStCJukT15Lh2j93qo9A).
If you already have a data source connected, you can choose it from the list, otherwise you’ll be prompted to create a new connection to your selected data source. In the example below, we’re selecting Airtable as the data source.

Airtable requires us to select the Base and Table we want to use for the Users of our app, but some datasources ask for other criteria such as “Solution”, “Workspace”, “Table”, or “Sheet”.

### Filtered User Sync
Softr let’s you choose who should be counted as a user. The Records section allows you to sync **All** users from the data source, or you can choose **Selected** to setup rules for who should be synced as a User of your app.
This is extremely helpful for when you may have lots of contacts, but only certain ones need access to the app. For instance, app subscribers, internal team members, or contacts who have an approved status.
Click on the **Advanced** toggle will allow you to define when and how users are synced, deleted, or deactivated. When a new user signs up to the app or is added manually, you can either:
- **Create a new user record in the data source**
- **Let the user only exist in the Softr app, without a matching data source record.**
You can also control what happens to a user record if they even cease to meet the filtering criteria. For instance, if an employee leaves and you mark them as “Inactive” in your data source, you may want Softr to either:
- **Deactivate their user account** - deactivating a user retains their data source record and record in the Softr app, but they cannot login and they do not count towards your user limit. They can be reactivated at any time either manually or automatically by the sync rules.
- **Delete their user account** - deleting a user does not retain their data either in the data source or in the Softr app. They will not be able to login or reactivate their account.
- **Unsync the user with the data source** - User login is retained in the app, but is no longer synced with the data source. Any extraneous user fields in the data source become unavailable for use in filtering, user groups, etc. The user still counts towards your plan’s user limits.

### Mapping User Fields
Now that the source is selected, we need to map the fields that will be tied to the Users of our app. Only only field is required to generate a User. Other optional fields are available to add in the dropdown. Any fields not listed here will still be available for use in your app, but only these are necessary for Softr’s User management.

- **Email** **\***— this is the unique user identifier and how we are able to connect user records. Please do not edit email on the data source side.
- **Name (optional)**
- **[Magic link](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/add-or-import-users-manually/g5R1bGnBTFJ3sWLR8Mgdng)** **(optional)**
- **Avatar (optional) —** instructions on setting up avatar can be found [here](/data-sources/1YYStCJukT15Lh2j93qo9A)
- **Created date (optional)** the date when the user was created
- **Last seen date (optional)** — the date when the user last used the application. Updated once per hour.
> **Tip**
>
> The **Last Seen Date** data is available to **Professional, Business, and Enterprise plan** users only. This field is updated once per hour.
### Authentication Method
Lastly, you’ll want to choose the method by which your users should be able to login with for the first time. You can either send them a Magic Link, which will automatically log them in, or you can send them a temporary password and let them reset their password later.
Using these methods is optional, but especially helps in onboarding new users for the first time. Which one you choose will determine which [Email Template](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/automated-user-invitations/3Jhs4orvsie7byu15BWmuV) is sent when Inviting new users to your app.
Once finished, click on the **Save and sync** button in the lower right corner of the popup modal.

Softr will begin syncing users from your data source into your app and you will begin to see users populating in your Users menu.

## How does 2-way syncing work?
> **Tip**
>
> Below logic is based on **2-way sync**. If you have applications created before June 2023, you’ll have to manually enable 2-way sync on each of them.
- **Adding user:** Any user created via Softr will get added to your connected source, and vice versa.
- **Deleting user:** Any user deleted via Softr will also get deleted from the source. **However, deleting a user from source will not delete user in Softr, and the user will be added back in the next sync** (we do this to prevent unrecoverable mistakes).
- **Changing user data:** Fields such as `Last seen date` and `Magic link` only make sense to be managed via Softr. If you edit the value from the source, it will be overridden on the next sync.
> **Note**
>
> Please DO NOT edit a user’s `Email` from the source. Softr will not be able to identify that user.
## When does syncing happen?
If your app’s user table syncs with a datasource, any new user added to your source table will get synced to Softr immediately. User syncing is not continuous inside of Studio or on unpublished apps. Only when you publish your app will user sync be realtime and continuous. You can also pause auto-sync at anytime in the connection settings:

We’ve also defined many syncing triggers inside of Softr Studio to ensure your app always gets the latest user data when it actually needs it. A few examples:
- When a user logs into an app.
- When you publish new app changes.
- When you visit the Users tab.
If you run into any cases where the data isn’t getting synced, and it’s affecting how your app works, please let us know!
## Syncing issues
If there’s an issue with syncing with a data source (e.g. you have a duplicate user in your data source), you’ll be notified about that as shown below.

_Sync issue notification_
Click on **See details** to learn more and address the issues. After successfully fixing the issue, hit **Validate fix** to trigger a sync.

## Enabling 2-way sync on older apps
User syncing between Softr and data source used to be 1-way (from application to data source only). If you have an app created before the introduction of 2-way sync in June, 2023, you’ll have to manually enable 2-way sync by going to the Users tab.

_Enabling 2-way sync_
---
# Add or import users manually
Source: https://docs.softr.io/add-and-manage-users/add-or-import-users-manually
To manually add users to your Softr app, you can click on **Add user(s)** button.

_Add user(s) button_
### **Adding a single user**
To add a single user, go to **ADD USERS** tab:
1. Enter the `Name` and `Email` of the user you want to add.
2. Select the authentication method. (We’ll explain more below)

_Adding a user_
If you choose to generate a temporary password, after hitting **Save and continue**, the user will be created, and you'll be taken to the next screen with user credentials.
You can either:
- **Finish without inviting**
- **Create invite,** which will allow you to send an email to the user with his/her login credentials included.

_User added_
In the future, if you need to resend the invite, you can select the user from the list and choose the **Resend Invite** action as shown below.

_Resend invite to a user_
### **Import users**
To bulk import multiple users, go to **IMPORT USERS** tab:
1. Upload the CSV file that contains your user data.
2. Map `Email` field.
3. (Optional) Map the `Name` field.
4. Select the default login method the users will use to login to the app for the first time. You can choose to generate a temporary password or generate a magic link. We recommend asking them in the invite email to visit their profile and change their password on first login.

Click **Add Users**, then you can select whether you want to send Invites to all Users now or send invites later.

Clicking **Invite Now** will open another popup where you can customize the Invite email that will be sent to the users. You can send a test email to yourself to see how it will appear. You can use handles to reference dynamic data within the email as well:
- **@application\_name** - will automatically populate the published name of your application
- **@application\_hyperlink** - will automatically populate a link to your published application
- **@user\_name** - will automatically populate the user’s imported name
- **@user\_email** - will automatically populate the user’s imported email
- **@password** - will populate the user’s Softr-generated temporary password, if you chose this option
- **@magic\_link** - will populate the user’s Softr-generated magic link, if you chose this option

_Example email using password handle_

_Example email using magic link handle_
---
# Internal vs. External Users
Source: https://docs.softr.io/add-and-manage-users/internal-vs-external-users
> **Warning**
>
> Note that the Internal/External User distinction is only applicable to legacy [V3 pricing plans](https://www.softr.io/pricing-v3) available before August 13, 2024. [Current V4 pricing](https://softr.io/pricing) plans do not distinguish between internal and external users. For more information, please see [this blog article](https://www.softr.io/blog/pricing-updates-2024).
> **Note**
>
> Maximum number of internal and external users allowed for a given app depends on the subscription plan. See V3 pricing [plan comparison](https://www.softr.io/pricing).
## Internal vs. external users
When you [Add users to a Softr app](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/add-users-to-a-softr-app/kBJGPeH635j7HDW4NYoDDs) they will be identified as internal or external users. **Internal** users are those who meet **any** of these criteria:
- They share the same email domain as any of the [collaborators in the workspace](/workspace-and-billing/jZP6yaeXMiJCuB6HhS4xKd/workspaces-and-applications/kTbEWSYXhBCbtTB4K9dpKs), including the workspace owner.
- Their email domain is whitelisted in the domain-based signup.
**External users** are those who don't meet any of the above criteria.
## Examples
Consider an [internal tool](/how-to-guides/ioi5BbuQ2RDM7aHPrpXnjG/what-internal-tools-can-you-build-with-softr/6DAy3i2YZPSLWV5Xd48ajC) like an applicant tracking system for company "XYZ".
- Head of HR () is added as a workspace collaborator to work on the application. If she’s also added to your app as a user, she’s considered an **internal user**
- HR managers like invited as users to your application, are also **internal users**, because they share the company's email domain xyz.com.
- Applicants added as users to your app with different email domains are considered **external users**.
In another scenario, for an [employee directory](https://www.softr.io/templates/employee-directory) at company "YZX", only employees with the whitelisted "yzx" email domain can sign up. This makes them **internal users**.
---
# User Email Notifications
Source: https://docs.softr.io/add-and-manage-users/user-email-notifications
User email notifications refer to the transactional messages that are sent in a response to an action users take on an application. In order to ensure these messages are relevant to your app users, Softr allows you to edit email notification templates.
Softr currently supports the below scenarios:
### Invite email via password
This email provides a temporary password for users added to the app by an app builder. The email can be sent at any time by the app builder and may be resent if necessary.
[Learn how to add users manually.](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/add-or-import-users-manually/g5R1bGnBTFJ3sWLR8Mgdng)
### Invite email via magic link
This email provides a special magic link for users added to the app by an app builder. The email can be sent at any time by the app builder and may be resent if necessary.
[Learn how to import users manually.](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/add-or-import-users-manually/g5R1bGnBTFJ3sWLR8Mgdng#import-users)
### Verification email
An email sent to allow users to obtain a code to sign in to this app. This email will be automatically triggered when a user requests a login code via the sign-in page.
A [Sign in with Email Code](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/signin-with-email-code/5Ab4ZFWG788NHL2AB6zt2f) block must be used to enable this option.
### Forgot password email
An email sent to allow users to reset their password when they have forgotten it. This email will be automatically triggered when a user requests a password reset via the sign-in page.
Make sure you have added [Forgot Password Form](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/forgot-password-form/cdXruGUfrkDNtzJi5JWx9s) and [Reset Password Form](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/reset-password-form/1Z48Ai2XvMX3JwuSq9ZU38) blocks to your app.
## Editing notification templates
To edit notification templates, click on the Notifications tab in the Users Menu of Softr Studio. Here you’ll be able to see each of the above notification templates. Click into a template to begin editing.
From here, you can change the subject line, adjust the content of the email, and leverage the power of variables.

> **Tip**
>
> The greyed out Softr informational text cannot be changed or removed when using the Softr email sending domain. This is to protect email recipients and legitimate Softr users. If you wish to send more customized emails, consider using automation software (Make, Zapier) and a transactional email service provider such as Mailersend, SendGrid, Mandrill, or Brevo.
### Variables
Variables are dynamic inputs to your message. They are defined by user and application level data points. For example, the variable @user\_name is a user level attribute and will populate as the notification recipient’s name when the email is delivered.
************************************Required variables************************************
Each template has a unique list of required variables. Required variables are critical pieces of information required in each scenario. For example @login\_code is required for the Verification email notification. Without it app users would not be able to sign in.
> **Tip**
>
> To avoid errors when editing templates, we prevent you from removing required variables.
**Optional variables**
Optional variables can be added to any email template. Leverage optional variables to personalize your messages, making them more relevant for your users. You have the option to add and remove optional variables.
## **List of variables**
### Invite email via password
| | |
| ----------------------- | ------------ |
| **Variable Name** | **Required** |
| @user\_email | Yes |
| @password | Yes |
| @application\_hyperlink | Yes |
| @application\_name | No |
| @application\_domain | No |
| @application\_owner | No |
| @user\_name | No |
### Invite email via magic link
| | |
| ----------------------- | ------------ |
| **Variable Name** | **Required** |
| @magic\_link | Yes |
| @application\_hyperlink | No |
| @application\_name | No |
| @application\_domain | No |
| @application\_owner | No |
| @user\_email | No |
| @user\_name | No |
### Forgot password email
| | |
| ----------------------- | ------------ |
| **Variable Name** | **Required** |
| @reset\_password\_link | Yes |
| @application\_hyperlink | No |
| @application\_name | No |
| @application\_domain | No |
| @application\_owner | No |
| @user\_email | No |
| @user\_name | No |
### Sign in with code
| | |
| ----------------------- | ------------ |
| **Variable Name** | **Required** |
| @login\_code | Yes |
| @application\_hyperlink | No |
| @application\_name | No |
| @application\_domain | No |
| @application\_owner | No |
| @user\_email | No |
| @user\_name | No |
## Sender details
You can customize the sender details for your email notifications. To edit Sender Details, click on the Notifications tab in the Users Menu of Softr Studio. Here, you can provide a sender name and email address. The email address does not need to have an actual Inbox, however you should ensure any replies sent to it are forwarded or handled appropriately so you can verify it. Alias emails will still work.
> **Tip**
>
> NOTE: **You cannot use a public email domain**. Email service providers restrict this to reduce security risks, such as phishing. You can only send from emails with custom domains.
Once you have entered the name and email you want to send from, you will get an email from our service provider, Postmark, asking you to verify email to enable sending from it. Be sure to click the verification button/link in the Postmark email. Come back to Softr to check that it has been verified. You can always click the Refresh button to re-check.

## DKIM Authentication
Ensuring that transactional emails from Softr apps reach their intended recipients is crucial for maintaining user engagement and satisfaction. Unfortunately, these emails can sometimes be blocked or end up in spam folders, leading to frustration and additional support overhead. Verifying the Sender Details (like in the step above) is a good first step, but by implementing DKIM (DomainKeys Identified Mail) verification, we can significantly improve email deliverability. This guide will walk you through the process of setting up DKIM for your domain to ensure consistent, reliable email delivery.
### Setup
After setting your custom sender details, the DKIM setup option will become available. Clicking on the **Verify** button will open a popup modal showing you the DKIM records that need to be added to your DNS.

1. **Requesting a DKIM record**\
- Open the DKIM setup modal. Softr will generate and return a DKIM record for your domain.
2. **Adding the DKIM record to tour DNS provider**\
- Add the provided DKIM record to your DNS provider. This step is crucial for enabling DKIM for your domain. Below are general instructions for adding DKIM records to various DNS providers:
- **GoDaddy:**
1. Log in to your GoDaddy account.
2. Go to the DNS management page for your domain.
3. Click "Add" and select "TXT" as the record type.
4. In the "Name" field, enter the host name provided in your DKIM record.
5. In the "Value" field, enter the value provided in your DKIM record.
6. Save the changes.
- **Cloudflare:**
1. Log in to your Cloudflare account.
2. Select your domain.
3. Go to the "DNS" tab.
4. Click "Add record" and select "TXT" as the record type.
5. Enter the host name and value provided in your DKIM record.
6. Save the changes.
- **AWS Route 53:**
1. Log in to the AWS Management Console.
2. Open the Route 53 console.
3. Select the hosted zone for your domain.
4. Click "Create record set."
5. Select "TXT - Text" as the record type.
6. Enter the host name and value provided in your DKIM record.
7. Save the changes.
- **Google Domains:**
1. Log in to your Google Domains account.
2. Select your domain.
3. Click on the "DNS" tab.
4. In the "Custom resource records" section, click "Add."
5. Select "TXT" as the record type.
6. Enter the host name and value provided in your DKIM record.
7. Save the changes.
- **Namecheap:**
1. Log in to your Namecheap account.
2. Select "Domain List" from the left sidebar and click "Manage" next to your domain.
3. Navigate to the "Advanced DNS" tab.
4. Click "Add New Record" and select "TXT Record" as the type.
5. Enter the host name and value provided in your DKIM record.
6. Save the changes.
3. **Verifying the DKIM record**\
- Click the "Verify" button to check the status. Note that DNS changes can take up to 24 hours to come into effect.
- Once verified, Softr will automatically start signing emails with DKIM for your domain.
### Benefits of DKIM
- **Improved deliverability:** DKIM ensures that your emails are less likely to be marked as spam or blocked.
- **Enhanced security:** DKIM helps verify that your emails are indeed from your domain, reducing the risk of phishing attacks.
- **Consistency:** Automating DKIM setup through Postmark's API saves time and ensures reliable email delivery.
---
# Automated user invitations
Source: https://docs.softr.io/add-and-manage-users/automated-user-invitations
## Overview
You can automatically send users a custom invitation to join and login to your app for the first time after they’ve been added as a user. This applies to users added in Softr Studio and users added directly to the data source side. To turn these on, go to the Users menu panel, click on the Notifications tab, then turn on the toggle in the Automation section.

## Customizing the Invitation Email
If no [Sender Details](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/user-email-notifications/sZRpewgUkBFFvhKSsQrBx7#sender-details) are setup, the invitation email will be sent from a Softr email domain.
To customize the actual email that is sent, you can click on the Invitation email templates in the Templates section below. Find all the details about editing Email Templates [here](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/user-email-notifications/sZRpewgUkBFFvhKSsQrBx7#invite-email-via-password).

---
# Notification Center
Source: https://docs.softr.io/add-and-manage-users/notification-center
The notification center is an inbox inside your published app. Logged-in users open it from the navigation menu to catch up on what needs their attention: comments and mentions on records they follow, and custom notifications that you send from a workflow.
Notifications wait in the inbox until the user reads them, so nothing is lost if they weren't online when it was sent. Unlike push notifications, the inbox needs no browser permission from the user.
> **Note**
>
> In-app notifications are available on paid plans, starting with the Professional plan. On a plan that doesn't include them, the toggle shows a plan badge and can't be turned on.
## What appears in the inbox
The inbox collects two kinds of notifications:
- **Comments and mentions.** When someone comments on a thread a user follows, or mentions them in a [Comments block](/building-blocks/comments-block), the user gets a notification in the inbox.
- **Custom notifications from workflows.** Any workflow can send a notification to one or more users with the [Send Notification](/workflows/actions/send-notification) action — for example, when a task is assigned to them, an invoice is due or a request needs approval.
Notifications only go to **logged-in users** of your app. Visitors who aren't signed in never see the inbox.
## Turn on the notification center
1. **Open the Notifications settings**
In Softr Studio, open your app and go to **Users** in the top bar, then select the **Notifications** tab.
2. **Switch on In-app notifications**
Under **Other channels**, turn on the **In-app notifications** toggle (1). This adds a **Notifications** link to your app's navigation menu. Use **Notification inbox** (2) to customize the inbox — see [Customize the inbox](#customize-the-inbox) below.

_The In-app notifications toggle and the Notification inbox settings link, under Other channels._
3. **Publish your app**
Changes to notification settings take effect once you [publish your app](/publishing/publishing-your-softr-app). Notifications are only delivered from a published app.
> **Tip**
>
> **Push notifications** sit right below the in-app toggle. They reach users in their browser or device even when your app isn't open, but users must allow them first. You can use both channels together — the [Send Notification](/workflows/actions/send-notification) action lets you pick Push, In-app or both for every message.
## Customize the inbox
Click **Notification inbox** next to the toggle to open **Notification inbox settings**. Every text your users see in the inbox can be changed here, so you can rename it or translate it into your app's language.
### General
- **Link label and icon** — the name and icon of the link in your navigation menu. It's **Notifications** with a bell icon by default.
- **All notifications tab** — the **Tab name** of the tab that lists every notification (**All** by default) and the **Empty state message** shown when there are none.
- **Unread notifications tab** — the **Tab name** of the tab that lists only unread notifications (**Unread** by default) and its **Empty state message**.

_The General tab of Notification inbox settings, where you set the navigation link and the tab names._
### Actions
- **Filters** — the labels of the two filter options: **All notifications** and **Comments only**.
- **Mark as read** — the labels (and icons) of the **Mark as read** and **Mark as unread** actions on a single notification, and the label of **Mark all as read**.

_The Actions tab of Notification inbox settings, where you rename the filters and the read/unread actions._
Click **Save** to keep your changes, then publish your app so users see them.
## Send notifications from a workflow
To send your own notifications to the inbox, add the **Send Notification** action to a workflow.
1. **Add the action**
In a workflow, add a step, choose **Softr Apps**, then **Send Notification**.
2. **Choose the In-app channel**
Under **Channels** (1), keep **In-app** selected. Remove **Push** if you only want the notification to go to the inbox.
3. **Pick the recipient**
In **User email** (2), enter the email of the user to notify, or map it from an earlier step with **@** — for example, the email of the user who triggered the workflow. The recipient must be a user of the selected app.
4. **Write the message**
Fill in the **Notification title** and, optionally, the **Notification body** (3). Both accept values from earlier steps, so you can include a record name, a due date or a status.
Optionally, set **Open URL on click** to the page the user should land on when they click the notification. It must start with your app's domain. If you leave it empty, clicking the notification opens your app's home page.

_The Send Notification action set to the In-app channel, with a recipient, title and body._
For every setting of the action, see [Send Notification](/workflows/actions/send-notification).
> **Warning**
>
> The action only delivers from a **published** app with **In-app notifications** turned on. If your app isn't published yet, a real test of the step fails with an "Application is not published" error.
## What your users see
Once the notification center is on, logged-in users see a **Notifications** link at the top of your app's navigation menu (1). Clicking it opens the inbox as a panel next to the menu.

_The notification inbox, opened from the Notifications link in the navigation menu, with the filter menu open._
In the inbox, users can:
- Switch between **All** notifications and **Unread** ones.
- Use the filter icon (2) to show **All notifications** or **Comments only**.
- Mark a single notification as read or unread, or use the **⋯** menu to **Mark all as read**.
- Click a notification to open the page it links to.
> **Note**
>
> To check how a notification looks, log in to your **published** app as the recipient and open the inbox after the workflow runs.
## Related
[**Send Notification**](/workflows/actions/send-notification)
Every setting of the workflow action that sends push and in-app notifications.
[**Comments block**](/building-blocks/comments-block)
Let users comment on records and mention each other.
[**User email notifications**](/add-and-manage-users/user-email-notifications)
Edit the email templates and sender details for your app.
[**Workflows**](/workflows/workflows)
Automate tasks and processes in your Softr apps.
---
# Signup Form
Source: https://docs.softr.io/add-and-manage-users/signup-form
> **Warning**
>
> This method of Signup is only for [Legacy Softr Apps](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/migrating-app-versions/4ASdHE4RECmauL82yzcVam). For the new Signup blocks and method for authentication, see the articles on [User Authentication](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/user-authentication/7gJmq6B7syYE3hRoFxLs5J), [Utility Blocks](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/utility-pages/49UoDpTpTPbkoKVwksoqfh), and the [Signup](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/signup/54HYs3JEjYZA33S96fP3de) utility page.
## Logo, Title, and Background Image
Under the Features tab of block settings, you can add a logo to the block, change the title, as well as set a background image for the whole block.

## Signup Form
### **Sign up with Google**
If you enable this option, a **Sign up with Google** button will be added to the form, allowing your users to sign up with their Google Accounts.

_Signup with Google_
> **Tip**
>
> To enable Google Signup, you first need to add your Google APP Client details in **Integrations => Google Sign In**. You can find instructions on getting the **Client ID** and **Client Secret** [here](/integrations/etS18kJqm1fuD58KCsjC3z/google-sign-in/2hBabh9UqoE8W7aWrfPVFd).
### **Domain-based signup**
Here, you can allow users to sign up only from specified domains. To do so, you need to add these domains inside the **Allowed domains** field. For instance, if you want only people with "softr.io" domains (e.g. ) to sign up, you need to enter "softr.io" into **Allowed domains** and hit **Enter** (see below). You can add as many domains as needed.

_Adding allowed domains_
## Form fields
### **Default Fields**
By default, you have three fields: **Name**, **Email**, and **Password,** where the **Name** field can be enabled or disabled. The placeholder texts of these fields can be modified as well. However, it's also possible to add any number of additional fields after connecting an Airtable users base, which we'll discuss next.
### **Adding Custom Fields**
You also have the option of customizing the Signup block by adding more fields. The values of additional fields will be stored in your [data source](/4230abecf813402aa2926466c313290a), therefore you need to have [a data source connected](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/syncing-users-with-a-data-source/hshRGygHr4T33EnaLntGf9) in the **Users** section. If you haven't connected a users base data source yet, you'll see a **Create Data Source** option under the **Signup Form** section in the **Features** tab.

_Create Data Source option_
After clicking the **Create** button, you'll need to follow the process described [here](/integrations/etS18kJqm1fuD58KCsjC3z/google-sign-in/2hBabh9UqoE8W7aWrfPVFd) to connect a data source where user data will be synced. Further on, in your database, you can define additional fields to store extra user parameters and add those to the **Signup** form as well. Let's consider a specific example to give you a better idea of how this works.
Let's connect an Airtable users base, where we have added an additional **Position** field that indicates the position of the registered employee within the company.

_Users base with additional parameter_
Now, we can add a position field to our Signup form and link it to this field on Airtable as done below.

_Additional Position field_
As a result, the users can now select a **Position** on signup, and it will be stored in the connected Airtable base as shown below.

_Additional Signup field stored on Airtable_
### **Sign Up Button**
Lastly, there's the **Sign Up** button. The button **Text** can be changed, while the **Action** is predefined and can't be modified.
## Terms and Conditions
Here, you can choose if you want to display a **Terms & Conditions** checkbox on the form, so that the users have to accept it before proceeding with the registration. If the checkbox is enabled, there are two fields for linking **Terms** and **Privacy Policy** pages.
## Show Sign In
Choose whether you want to show a sign-in button (takes the user to the sign-in page) or not.
## On Sign up
Lastly, we need to set what page the user should be taken to after successfully signing up.

_Configuring page after signup_
## **Enable reCaptcha**

_Enabling reCaptcha on Sign Up form_
By adding reCaptcha authentication to your sign up form, you'll protect it from getting spammed or misused.
> **Tip**
>
> Please, note that Softr only supports [reCaptcha v3](https://developers.google.com/recaptcha/docs/versions).
To set up reCaptcha, you need to go to
and enter your site details as shown below.

_reCaptcha setup_
In the next screen, you just need to copy the **Site Key** and **Secret Key.**

_Getting Site Key and Secret Key_
To finalize the setup, paste the Site Key and Secret Key in your Softr app's **Settings => Integrations => Google reCaptcha.**

_Adding reCaptcha keys_
## Block visibility
The block is visible to all visitors of the app, and you have no control over its visibility, hence the default visibility setting is set to "Non-logged in users”.
---
# Signin Form
Source: https://docs.softr.io/add-and-manage-users/signin-form

_Signin Form_
## Logo, Title, and Background Image
You can configure these features in the Features tab in block settings, which is done the same way as on the [Signup Form](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/signup-form/tPe3uxmdcUNeFYuaLTR1o9).
## Signin Form
### **Sign in with Google**
If you enable this option, a **Sign in with Google** button will be added to the form, allowing your users to sign in with their Google Accounts.

_Google Signin_
> **Tip**
>
> To enable Google Signup, you first need to add your Google APP Client details in **Integrations => Google Sign In**. You can find instructions on getting the **Client ID** and **Client Secret** [here](/integrations/etS18kJqm1fuD58KCsjC3z/google-sign-in/2hBabh9UqoE8W7aWrfPVFd).
If the **Only registered users can sign in** toggle is enabled, only the users that already have an account on your Softr app will be able to sign in with Google.
## Form Fields
### **Email and Password**
Here, you can configure the **Email** and **Password** fields. The placeholder texts of these fields can be modified.
### **Sign In Button**
Lastly, there's the **Sign In** button. The button **Text** can be changed, while the **Action** is predefined and can't be modified.
## Forgot Password
You can enable this option to provide your users with a link to a page where they can reset their password. On that page, you simply need to add a [Forgot Password](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/forgot-password-form/cdXruGUfrkDNtzJi5JWx9s) block, where the users can enter their email and get a link to do a reset.
## Show Signup
You can add an option to go to your [Signup page](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/signup-form/tPe3uxmdcUNeFYuaLTR1o9) for those users who have landed on your Signin page but don't really have an account in your Softr app yet.
## On Signin
Lastly, you should choose which page the users are taken to after signin.
## Block visibility
The block is visible to all visitors of the app, and you have no control over its visibility, hence the default visibility setting is set to "Non-logged in users”.
---
# Signin with Email Code
Source: https://docs.softr.io/add-and-manage-users/signin-with-email-code

_Signin in with code_
> **Tip**
>
> This feature is only available to **Professional** and **Business** users.
Using this sign-in block, you can allow your users to log in using a random code sent to their email instead of entering a password. Let's quickly review the block settings.
> **Tip**
>
> The code will be valid **for 5 minutes** after being sent.
## **Signin Form**
If the **Only registered users can sign in** toggle is enabled, only the users that already have an account in your Softr app will be able to sign in using this block.
The Domain-based signup option works similar to that of the [Signup Form](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/signup-form/tPe3uxmdcUNeFYuaLTR1o9).
1. **Step 1: Email**
Here, you can customize the Email field placeholder text as well as the text on the send button.
2. **Step 2: Code**
The code field placeholder text and Signin button text can also be customized.
## **On Signin**
Finally, you need to choose the page the the users will be taken to after signin.
## Testing
Now, let's see how the block works from the user's standpoint. In the first step, the user needs to enter his/her email address as shown below.

_Entering email_
Next, a random code will be send to user's mailbox, which he/she should use in the **Sign in code**
field to log in. See below.

_Logging in with the received code_
That's. It only takes a few seconds to get the code and enter the site.
---
# Sign in with SMS Code (deprecated)
Source: https://docs.softr.io/add-and-manage-users/sign-in-with-sms-code-deprecated
> **Warning**
>
> On 13th June 2024, we discontinued SMS code as a sign-in method in Softr apps. Don’t worry, **if your apps have SMS sign-in, they’ll continue to work for your users. No action is needed.**
**Why did we discontinue SMS sign-in**
We introduced SMS as sign-in method two years ago. Our product has evolved rapidly since, and we’ve realized that the unique nature of SMS sign-in + our specific implementation created technical debts that prevent us from introducing bigger improvements around user management. Therefore, we made the tough decision to discontinue it.
**What’ll happen to my existing apps with SMS sign-in in the long-term?**
For the foreseeable future, we will continue to support your existing apps with SMS sign-in. In the long term, we might either:
1. Sunset it completely
2. Offer a new, better version
In either case, you’ll be notified way beforehand and offered an easy way to migrate, so it won’t create disruption for your users or too much admin burden on you.
## Overview

_Signin with Phone Code_
> **Tip**
>
> This feature is only available to **Business** users.
Using this sign-in block, you can allow your users to log in using their phone number (i.e. receive a verification code via SMS and use that code to sign in). So, let's first review the block settings.
> **Tip**
>
> The sms code will be valid **for 5 minutes** after being sent.

_Block settings_
First of all, you can choose if the sign-in should be available **just for registered users** or for anyone. If the toggle is not enabled, any visitor can enter his/her phone number, receive the code, and log into your Softr app.
Further on, you can change the placeholder text of the two fields (**Phone** and **Sign in Code**) and also the **button labels**.
## **Sign-in process**
Now, let's see how the block works from the user's standpoint. In the first step, the user needs to enter his/her phone number as shown below.
> **Tip**
>
> Please, note that the block only support phone numbers starting with a \*\*valid country code (\*\*e.g. "+49" for German phone numbers).

_Entering phone number_
After submitting the phone number, the user will receive a 6-digit code to his/her mobile phone via SMS and needs to provide that code in the next step to verify his/her account.

_Verifying user account_
That's it. As soon as the user submits the verification code, he/she will log in to your Softr app, becoming a verified user.
## **User Creation**
Although, when signing in through this block, the user doesn't provide an email address, the email field is still mandatory and needs to be assigned to the user account. Therefore, every time a user signs in using a phone number, an email address is generated automatically for him/her in the following format:
**<+xxxxxxxx@softr-applicationID.app>**
Here, the **"+xxxxxxxx"** represents the user's phone number, and the **"applicationID"** is replaced by the actual application ID of your Softr app.
## **Syncing with Airtable**
**If you have your users base** [connected to Airtable or any other data source](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/syncing-users-with-a-data-source/hshRGygHr4T33EnaLntGf9)**, the users created via sms verification will be synced to the data source without issues (using the email that was generated automatically upon signin).**
However, let's consider the case when you have a particular user on Airtable but don't have that user in your Softr app and want to sync those two entries as soon as the given user signs in through your Softr app. To make it possible, both entries need to have the exact same email address.
Therefore, on Airtable, your **Email** field should be a **formula** that combines user's phone number and your **application ID** using the format discussed above (**<+xxxxxxxx@softr-applicationID.ap>**p), so that the result matches exactly the email generated automatically when the user signs in through the Softr app.
> **Tip**
>
> [Google Sheets](/data-sources/1YYStCJukT15Lh2j93qo9A/google-sheets/jznC9Jr3Jri224AVmHVn4a) doesn’t have an option to use formulas, therefore syncing users this way **will be possible only with Airtable**.
In order to set up the formula on Airtable, you first need to get your **Softr Applciation ID**. It can be copied from the URL of your Softr app studio.Below, we show how you can copy it and paste into your Airtable users base.

_Adding App ID to Airtable_
Further on, let's create the formula that will concatenate user's phone number and Application ID into the required expression. Below, you can see what the formula looks like.

_Creating the formula_
So, you need to use a **CONCATENATE()** formula, where **\{Phone Number}** is the field where user's phone number is stored and **\{Application ID}** is your Application ID field on Airtable.
---
# User Profile
Source: https://docs.softr.io/add-and-manage-users/user-profile
> **Tip**
>
> This page covers the legacy User Profile block found in legacy apps (read more about legacy apps and migration [here](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/migrating-app-versions/4ASdHE4RECmauL82yzcVam)). New apps use the [Account Settings Utility page](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/account-settings/54HYs3JEjZj8DGwRCNUpH9) instead.

_User profile block_
The **User Profile** block allows your users to edit their info and password.
> **Tip**
>
> The link to the page with the **User Profile** block can be added under [Profile Links](/11ba304436ed4354a8669d4869624b9c) when **Show User Profile** is enabled on the **Header**.

_Adding a link to User Profile under Profile Links_
Now, let's check out what configuration options are available for the block.
## Background image

_Block’s background image option_
Here, you can set a background image for the block.
## My Profile
### **Default Fields**

_My Profile Default fields_
Here, you can configure the section **Title** as well as the placeholders of the **Name** and **Email** fields. Please, note that the **Update Profile** button's **Action** is predefined and cannot be changed.
Moreover, you have the **Avatar image** field (we’ll discuss it shortly), which can be deleted in case you don't need it.
### **Additional Fields**
If you've [connected users to a data source](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/syncing-users-with-a-data-source/hshRGygHr4T33EnaLntGf9) with additional user parameters, you can add more fields to the User Profile block and link them to these parameter fields in your data source, so that your users are able to edit those as well. If there's no data source connected yet, you'll see a **Create Data Source** button, which you can use to connect one. Let's examine this on a specific example.
Let's say our users are company employees that have a **Position** within the company. To account for that, we have an additional **Position** field in our users [Airtable](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX) along with its different options.

_Additional Position field on Airtable_
So, on the **User Profile** block, we can create a new field and link it to the **Position** field on Airtable.

_Mapping the position field_
Now, users will be able to edit their position from the user profile as shown below.

_User changing his/her Position_
## **Change Password**
Here, you can configure the placeholder texts of the **Change Password** fields and modify the section title.

_“Change Password” section_
## Enabling user avatar
Let's see how you can allow your users to upload avatar images to be shown on site header.
### **Enabling user profile on header**
First of all, you need to enable the "Show user profile" toggle on your Softr app header.

_Show user profile_
> **Tip**
>
> Make sure to update your header block, as the avatar functionality won't work on header blocks created before its introduction.
### **Mapping the avatar field to a data source**
Now, you need to map the avatar field to a [data source](/4230abecf813402aa2926466c313290a), so that images uploaded by users are stored there. You may or may not have your users base connected to a data source already. Let's consider the two cases separately as the workflow is a bit different for each.
**Data source is not connected**
If you haven't connected your users to a data source, you can do so from the **User Profile** block or [Users Tab](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/users-menu/5JTzjtbvp8Skemd26A9ho9), mapping the Avatar field. As soon as you do that, the Avatar field will automatically appear on your User Profile block as shown below. Below, you can see how we connect [Airtable](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX) and map the avatar field.

_Connecting Airtable and mapping the Avatar field_
Data source **is connected**
If you already have a data source connected, you can add a "File" type field in your User Profile block settings and map it to the corresponding field in the data source **manually**.
You need to edit your [data source connection](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/syncing-users-with-a-data-source/hshRGygHr4T33EnaLntGf9)

Then map **the same** field there as well (**Select Avatar field** option as shown in the screen recording above).
> **Tip**
>
> Note that mapping the field from **BOTH** the **User Profile**
> block and **data source connection** settings is **necessary** for enabling the avatar.
### **Avatar upload by the user**
That's it, now the logged-in users will see an option to upload an avatar on their **User Profile** and can update it at any time. See below how it works.

_User uploading an avatar_
---
# Forgot Password Form
Source: https://docs.softr.io/add-and-manage-users/forgot-password-form
In this form, users can enter their email to recover their password. As soon as you also set up a [Reset Password Form](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/reset-password-form/1Z48Ai2XvMX3JwuSq9ZU38), the user will enter the email address here, receive a recovery link on his/her email, and go to the **Reset Password** page via the link to provide a new password.

_Forgot Password form_
The animation below shows how that works.
> **Tip**
>
> Check out how to change the sender email and name [here](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/general-settings/7YdGy1J8X2tjJSv8BGvWQU).

_Resetting the Password_
Now, let's see how the block can be customized.
## Logo, Title, and Background Image
This section is configured similar to that of the [Signup Form](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/signup-form/tPe3uxmdcUNeFYuaLTR1o9).
## Forgot Password form

_Block settings_
Here, you can configure the placeholder text for the **Email** field and the **Recove**r button. The **Action** is fixed and cannot be changed.
## Confirmation Message
The **Confirmation Message** is the text that's shown after the user hits **Recover Password**. You can modify the text here.

_Password reset confirmation message_
See below how it works.

_Testing the password reset_
---
# Reset Password Form
Source: https://docs.softr.io/add-and-manage-users/reset-password-form
This article provides a guide on setting up the password reset process, outlining two available methods.
## **Password reset for logged-out users**
- Create separate pages for [Forgot Password Form](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/forgot-password-form/cdXruGUfrkDNtzJi5JWx9s) and discussed here "Reset Password" block.
- On the "Forgot Password" page, add the respective block where users can enter their email address.
- After submitting the email, users receive a unique link (e.g. `https://domain.softr.app/reset-password?token=bcb9702f-3579-49c9-be57-a01f5e93b4e1`) to reset their password.
- Ensure these pages are accessible to users who are not logged in, specifically for those who have forgotten their passwords.
- Refer to this instructional video for further assistance: [Password Reset Tutorial Video](https://www.youtube.com/watch?v=YEdfVQg2dAs).

_Resetting the password_
## **Password reset/set for logged-In users**
Use the [User Profile](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/user-profile/jVikpwBm67W9wozwyDXtjs) block to enable password resets for logged-in users.
> **Note**
>
> If users log in using a magic link and wish to set a password, they should navigate to a page with the user profile block. Note that even after setting a new password, the _Old password_ input field remains grayed out for these users.
## Logo, Title, and Background Image
This section is configured similar to that of the [Signup Form](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/signup-form/tPe3uxmdcUNeFYuaLTR1o9).
## Reset Password form
Customize the "New Password" field placeholder text and the "Reset" button text in this section. Note that the action of the button is fixed and cannot be changed.

_Block settings_
---
# Single Sign-on Overview
Source: https://docs.softr.io/add-and-manage-users/single-sign-on-overview
Single Sign-on (SSO) lets the people who use your Softr app log in with the account they already have at work — their Microsoft, Google Workspace, Okta, or other identity provider account — instead of creating a separate Softr password. Your IT team stays in control of who has access, and your users get one less password to manage.
This page explains how SSO works in Softr and walks through the configuration that is the same for every identity provider. Once you understand this flow, the provider-specific guides only tell you where to click inside that provider.
> **Note**
>
> SSO (SAML and OpenID) is available on the [Enterprise plan](https://www.softr.io/pricing). If you are on another plan, [contact sales](https://www.softr.io/contact-sales) to discuss enabling it.
> **Warning**
>
> **This page is about SSO for the users of your app.** If you want the _collaborators who build apps_ in your Softr workspace to log in to Softr Studio through your identity provider, that is a separate feature — see [SSO for Softr Studio](/security/sso-for-softr-studio).
## How SSO works in Softr
In SSO terms your Softr app is the **service provider (SP)** and your identity provider (**IdP**) is the system that actually holds the accounts and checks the credentials. When someone signs in:
1. They open your app and choose **Continue with SSO** on the login screen.
2. Softr hands them off to your identity provider.
3. The identity provider authenticates them — including any MFA, conditional access, or device policy you enforce there.
4. The identity provider sends Softr a signed response containing the person's email and name.
5. Softr signs them in and matches them to a user record in your app. Because step 3 happens entirely on your side, everything your IT team already enforces — MFA, session policy, deprovisioning when someone leaves — applies to your Softr app too, without Softr ever handling a password.

_The SSO handoff between a Softr app and an identity provider._
## SAML or OpenID?
Softr supports both of the standards that identity providers use, and you pick one per app. Most providers support both, so if you have no preference, use whichever your provider's documentation treats as the default path.
| | SAML | OpenID (OIDC) |
| ------------------------------ | ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| What it is | An XML-based standard for exchanging authentication assertions | An identity layer on top of OAuth 2.0 |
| What you give your IdP | **ACS URL** and **Audience URL** | **Callback URL** |
| What you paste back into Softr | **Metadata.xml**, plus the **Email**, **First name** and **Last name** attribute keys | **Provider URL**, **Token service URL**, **Client ID**, **Client secret** |
| Typical providers | Microsoft Entra ID (Azure AD), Okta, OneLogin, Google Workspace, Shibboleth, Keycloak | Outseta, Auth0, Keycloak, and any provider publishing an OIDC discovery endpoint |
> **Tip**
>
> If your provider offers a pre-built catalog entry for SAML apps, you will usually get there faster with SAML: the provider generates the metadata for you and you paste a single XML document into Softr.
## Before you start
Have these ready — the configuration screen asks for all of them and you will be switching between two browser tabs:
**Admin access to your identity provider**
You need to be able to create a new application (sometimes called an app integration, enterprise application, or OAuth client) in your IdP, and to configure which attributes it sends.
**A decision on SAML vs OpenID**
See the comparison above. You can change it later, but you will have to redo the setup on the provider side.
**The email domains your users sign in with**
For example `acme.com` and `acme.co.uk`. These are optional, but setting them changes how the login screen behaves — see [Routing users to SSO automatically](#routing-users-to-sso-automatically).
**A plan for user groups**
SSO controls _who can get in_. It does not by itself decide what each person can see. Plan how signed-in users map to [user groups](/user-groups-and-permissions/user-groups) before you roll SSO out.
## Configure SSO
1. **Open your app's authentication settings**
In Softr Studio, open your app and go to the **Users** tab, then the **Authentication** sub-tab. This is where every login method for the app is managed.

_The Authentication screen, where all of an app's login methods are configured._
2. **Turn on Single Sign-on**
In the **Authentication method** list, switch the **Single Sign-on** toggle on. The **Single sign-on** configuration window opens straight away. Once the method is on, a gear icon appears next to it — use that to reopen the configuration at any time. An amber dot next to **Single Sign-on** means the method is enabled but not yet fully configured.

_The Single Sign-on toggle in the Authentication method list._
3. **Choose your SSO type**
At the top of the window, set **SSO type** to **SAML** or **OpenID**. The fields below change to match your choice.

_The SSO type dropdown, offering SAML and OpenID._
4. **Share Softr's details with your identity provider**
Under **1. Share the following details with your identity provider**, Softr shows the values your IdP needs in order to trust your app. Copy each one with the button at the end of the field.
**SAML**
- **ACS URL** — the Assertion Consumer Service sign-in URL, in the form `https://.softr.app/saml/SSO`. Your identity provider posts its response here. Some providers call this the _Reply URL_, _Recipient_, or _Single sign-on URL_.
- **Audience URL** — the entity ID, a unique identifier for your app. Providers may label this _Audience (EntityID)_, _Identifier_, or _SP Entity ID_.
**OpenID**
- **Callback URL** — the redirect URI, in the form `https://.softr.app/open-id/code`. Providers may label this _Redirect URI_, _Sign-in redirect URI_, or _Callback URI_.

_Softr shows the ACS URL and Audience URL to give to your identity provider._
> **Note**
>
> If your app uses a [custom domain](/publishing/add-a-custom-domain-to-your-app), confirm which hostname these URLs use before you register them with your provider — the values Softr shows here are the ones your provider must trust.
5. **Create the application in your identity provider**
Switch to your identity provider and create a new application, pasting in the URLs from the previous step. Then configure what the provider sends back:
- **For SAML**, add attributes for the user's email, first name, and last name, and make sure each is included in the SAML assertion. Note the exact attribute names — you need them in the next step.
- **For OpenID**, note the **Client ID** and **Client secret** the provider generates, along with its authorization and token endpoints.
The provider-specific guides at the bottom of this page cover this step in detail. If your provider is not listed yet, its own documentation for adding a custom SAML or OIDC application will use the same values.
6. **Enter your identity provider's details in Softr**
Back in the **Single sign-on** window, fill in **2. Enter the following details from your identity provider**.
**SAML**
- **Metadata.xml** — paste the full metadata XML document from your provider.
- **Email key** / **First name key** / **Last name key** — the exact attribute names you configured in your IdP, so Softr knows which claim holds which value.
**OpenID**
- **Provider URL** — your provider's OpenID Connect issuer or authorization URL.
- **Token service URL** — the endpoint Softr calls to exchange the authorization code for tokens.
- **Client ID** and **Client secret** — the credentials generated when you created the OAuth client.

_The OpenID fields: Provider URL, Token service URL, Client ID, and Client secret._
7. **Set your SSO email domains (optional)**
In **SSO email domains**, list the domains your workforce signs in with, separated by commas — for example `acme.com, acme.co.uk`. If your app offers other login methods as well, anyone whose email address matches one of these domains is always sent to SSO instead. See [Routing users to SSO automatically](#routing-users-to-sso-automatically).
8. **Save and publish**
Click **Save**. Then open the **Log in** utility page to check that **Continue with SSO** now appears, and publish your app so the change reaches your users.
## What your users see
You do not add an SSO block to a page. Softr's login screen is a built-in **utility page** called **Log in** (at `/login`), and enabling Single Sign-on adds a **Continue with SSO** button to it automatically.

_The Log in utility page with Continue with SSO enabled._
Select the login card in Studio to open the **Sign In** block settings, where you can adjust:
- **Logo**, **Title & subtitle**, and the **Side section** (background image, heading, text, image) to brand the screen.
- **Log in flows** — every authentication method enabled for the app is listed here with a visibility control, so you can hide a method on this screen without disabling it for the app.
- **Consent message**, **Redirect to sign up**, and **reCAPTCHA**.

_The Log in flows list in the Sign In block settings._
### Routing users to SSO automatically
The **SSO email domains** field decides how much choice your users get:
- **Left empty** — the login screen shows every enabled method side by side, and each person picks one.
- **Filled in** — anyone whose email address matches a listed domain is always directed to log in with SSO, even if other methods are available. Use this when your workforce must go through the identity provider while, say, external clients continue to use email.
## How SSO users appear in your app
Signed-in users show up under **Users → Users** like any other user. The **Auth method** column records how each person authenticates, so you can tell SSO users apart from those using email and password.

_The Users list, with the Auth method column showing how each person signs in._
Authentication is only half of access control. Once someone is signed in, what they can see is governed by [user groups](/user-groups-and-permissions/user-groups), [page visibility](/user-groups-and-permissions/page-visibility), and [record filters](/user-groups-and-permissions/record-filters). Configure those before inviting your users in.
> **Note**
>
> If you want the identity provider to create, update and deactivate Softr user records automatically rather than relying on people signing in, look at [SCIM User Provisioning](/add-and-manage-users/scim-provisioning), which is also on the Enterprise plan.
## Using SSO alongside other login methods
SSO does not have to be the only way in. Each method in the **Authentication method** list is independent, so a single app can offer SSO for employees and email login for external clients. Two things to keep in mind:
- **SSO email domains** override the choice for matching addresses, as described above.
- Hiding a method under **Log in flows** only changes that screen. To remove a method for the whole app, switch it off in **Users → Authentication**.
## Turning SSO off
Switching **Single Sign-on** off asks you to type `Remove Single Sign-on` to confirm, because it can lock people out.
> **Warning**
>
> Removing SSO as an authentication method means anyone who only ever signed in through your identity provider may no longer be able to log in. Make sure those users have another way in (or that you intend to revoke their access) before you confirm.
## Good to know
- **Softr is the service provider, never the identity provider.** You can let your identity provider log people in to Softr; you cannot use a Softr login to sign people in to other platforms.
- **One SSO configuration per app.** The configuration window holds a single identity provider. The **SSO email domains** field accepts several domains for that one provider — it does not connect several providers to the same app.
- **The configuration is per app**, not per workspace. An app you duplicate does not inherit a working SSO setup; register the new app's ACS/Callback URLs with your provider separately.
## Provider guides
[**SAML Single Sign-on**](/add-and-manage-users/saml-single-sign-on)
The SAML setup walked through end to end.
[**Microsoft Azure SAML Single Sign-on**](/add-and-manage-users/microsoft-azure-saml-single-sign-on)
Connecting Microsoft Entra ID (Azure AD).
[**OpenId Single Sign-on**](/add-and-manage-users/openid-single-sign-on)
The OpenID Connect setup, using Outseta as the example.
[**Google Sign In**](/integrations/google-sign-in)
A lighter-weight alternative for Google accounts.
Your identity provider's own documentation is the authority on its half of the setup. Useful starting points:
- Microsoft Entra ID — [Enable SAML single sign-on for an enterprise application](https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/add-application-portal-setup-sso)
- Okta — [Create SAML app integrations](https://help.okta.com/en-us/content/topics/apps/apps_app_integration_wizard_saml.htm)
- Google Workspace — [Set up your own custom SAML app](https://support.google.com/a/answer/6087519)
- OneLogin — [SAML Custom Connector (Advanced)](https://support.onelogin.com/kb/4266907/saml-custom-connector-advanced)
- Auth0 — [Configure applications with OIDC Discovery](https://auth0.com/docs/get-started/applications/configure-applications-with-oidc-discovery)
- Outseta — [Log users into multiple products with OpenID Connect SSO](https://go.outseta.com/support/kb/articles/amRZYjmJ/log-users-into-multiple-products-with-openid-connect-single-sign-on-sso)
## Related
[**User Authentication**](/core-concepts-overview/user-authentication)
How authentication works in Softr apps.
[**SCIM User Provisioning**](/add-and-manage-users/scim-provisioning)
Provision and deprovision users from your identity provider.
[**SSO for Softr Studio**](/security/sso-for-softr-studio)
SSO for the collaborators who build your apps.
[**Softr App Security**](/security/softr-app-security)
How Softr secures published apps.
---
# SAML Single Sign-on
Source: https://docs.softr.io/add-and-manage-users/saml-single-sign-on
To be able to configure and use the block, you first need to setup SAML for your Softr app. We’ll learn what SAML is and how to configure it for Softr shortly, but let’s first get familiar with block settings.
Next, you can enable [Domain-based signup](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/signup-form/tPe3uxmdcUNeFYuaLTR1o9) and customize the **login button text**. Finally, there's an option to set **which page the user should be taken to** after successfully signing in.
## **Single Sign-On Configuration**
In this section, we'll go through the steps of setting up **SAML (Security Assertion Markup Language)** for your Softr app. SAML is an open standard that allows **identity providers (IdP)** to pass authorization credentials to **service providers (SP)**, so that users can use a single set of credentials to log into different SPs. In this case your Softr app is the **SP**, and you need to connect it to an IdP to implement **Single Sign-On (SSO)** on your Softr app. There are several IdP services (e.g. Azure, Okta, Box) that you can use, but here we'll demonstrate the setup flow using [OneLogin](https://www.onelogin.com/). So, let's start.
1. **Configuring the Application**
In the Application settings, we are going to navigate to **Configuration** and fill in the following fields:
- **Audience (EntityID)**
- **Recipient**
- **ACS (Consumer) URL Validator**
- **ACS (Consumer) URL**
---
# OpenId Single Sign-on
Source: https://docs.softr.io/add-and-manage-users/openid-single-sign-on
> **Note**
>
> OpenId Single Sign-on (SSO) is available for users on the [Enterprise plan](https://www.softr.io/pricing).

_OpenId Single sign on block_
Using this block, you can enable your users to sign in with their OpenId credentials. To be able to use the block, you first need to integrate the OpenId platform that you use for user management and authentication. We’ll find out how to do that next.
## Configuring OpenId settings
[OpenID Connect (OIDC)](https://openid.net/connect/) is an open authentication protocol that extends the [OAuth 2.0](https://oauth.net/2/) protocol, adding an identity layer to it. There are a number of services that use the OpenId technology. Softr can be integrated with any platform using the OpenID standard. One such platform is Outseta membership software. Let’s use Outseta as an example for how to setup OpenID in your Softr app.
If you use Outseta as your user management and authentication solution, you can integrate it with Softr, allowing your users to log into your Softr app with their Outseta credentials. The integration steps are pretty simple and straightforward, so let's start.
### **Getting the Callback URL**
First, let's copy the **Callback URL** from our OpenId Settings. We are going to use it in our Outseta account, so let's switch there for a moment.
### **Adding an OAuth Client in Outseta**
First, we need to add an OAuth Client in our Outseta account. To do that, we need to navigate to **Settings => Integrations => OAuth** and hit **Add OAuth Client.**

_Adding OAuth Client_
In the pop-up that follows, we are going to add a **Name** for the client, paste the Callback ID we had copied earlier from our Softr app։ The Logout Redirect URL can be left blank.

_Configuring OAuth client_
After completing those, click Add, and the pop-up will expand, showing your **Integration Details**.

_Integration details_
Here, you need the **Client Id** and **Client Secret** values.
### **Adding Client Id and Secret on Softr**
Now we are going to add the **Client Id** and **Client Secret** values, which we obtained in the previous step, in our Softr app's **OpenId Settings**.

_Adding ID and secret_
> **Tip**
>
> As you can notice, we've added **** under **Provider URL**. In your case, the URL will have a similar structure, but "softr.outseta.com" will be replaced with your own Outseta domain: ****
After completing this, Save your settings, and you're done. Now, you can use the **OpenId SSO Softr block** to allow your users log in with their Outseta credentials.
### **Testing the Integration**
Let's pick a user from our Outseta contacts and try logging with this user's credentials on Softr. You can learn about user authentication, how users can sign up and create passwords, and more [here](https://www.outseta.com/authentication).
Below, you can see a contact that has passed authentication and has a password.

_A contact in Outseta_
Now, we can use this contact’s email and password to log into our Softr app through the OpenId login block. First, let’s set up the OpenId block.

_Adding the OpenId Signin block_
We can modify the layout of the block as well as change the page after signin, but we are going to leave it as it is. Now, let’s publish our app and try logging in with the Outseta user we mentioned earlier.

_Testing signin_
As you can see, we’re able to log in and out successfully.
> **Tip**
>
> As soon as the user signs in with his/her Outseta credentials, a new [user is created](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/users-menu/5JTzjtbvp8Skemd26A9ho9) in your Softr app.
---
# SCIM User Provisioning
Source: https://docs.softr.io/add-and-manage-users/scim-provisioning
> **Note**
>
> SCIM user provisioning is available for users on the [Enterprise plan](https://www.softr.io/pricing). Please [contact sales](https://www.softr.io/contact-sales) to enable this feature for your workspace.
## Overview
SCIM (System for Cross-domain Identity Management, [RFC 7644](https://datatracker.ietf.org/doc/html/rfc7644)) is the standard protocol that identity providers use to manage users in third-party apps. Once SCIM is connected, your IdP becomes the source of truth for who has access to your Softr app — when you add, update, deactivate, or remove a user in your IdP, the change is pushed to Softr automatically.
SCIM is the natural complement to [SSO](/add-and-manage-users/saml-single-sign-on): SSO authenticates a user when they sign in, while SCIM provisions the user record itself ahead of time and keeps it in sync. The two are typically used together for centralized identity management.
## Supported identity providers
Softr's SCIM implementation follows the SCIM 2.0 standard, so it works with any SCIM-capable IdP, including:
- Okta
- Microsoft Entra ID (Azure AD)
- OneLogin
- JumpCloud
- Google Workspace
- … and any other IdP that supports SCIM 2.0.
## What SCIM does in Softr
| Action in your IdP | Result in Softr |
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Assign a user to the Softr app | A user is created in your Softr app. If [auto-invite](/add-and-manage-users/automated-user-invitations) is enabled in the app's User Settings, the invitation email is sent automatically. |
| Update a user's name or email | The corresponding Softr user record is updated. |
| Deactivate a user (set `active: false`) | The user is deactivated in Softr and can no longer sign in. |
| Reactivate a user (set `active: true`) | The user is reactivated. |
| Unassign a user / delete from your IdP | The user is removed from your Softr app. |
## Prerequisites
Before configuring SCIM, make sure you have:
- An **Enterprise plan** with SCIM enabled by Softr — [contact sales](https://www.softr.io/contact-sales) if you haven't requested it yet.
- A **published Softr app**.
- A **Softr API key** — see [API Setup and Endpoints](/softr-api/api-setup-and-endpoints) for how to generate one.
- The **Application ID** of the Softr app you want to provision into.
## Connection details
Your IdP will ask for two values when you set up the SCIM integration: a base URL (sometimes called Tenant URL) and a Bearer token.
| Field | Value |
| ------------------------------ | ------------------------------------------------------------------------ |
| **SCIM Base URL / Tenant URL** | `https://studio-api.softr.io/scim/v2/applications/{applicationId}/Users` |
| **Authentication** | HTTP Bearer token — header `Authorization: Bearer YOUR_SOFTR_API_KEY` |
| **Content type** | `application/scim+json` |
Replace `{applicationId}` with the ID of your Softr application and `YOUR_SOFTR_API_KEY` with the API key you generated.
## Supported endpoints
| Method | Path | Purpose | Rate limit |
| -------- | ------------- | ---------------------------------------------------------------------------------- | ---------- |
| `GET` | `/Users` | List or filter users in the app. Supports pagination via `startIndex` and `count`. | 300 / min |
| `GET` | `/Users/{id}` | Retrieve a single user by ID. | 300 / min |
| `POST` | `/Users` | Provision a new user. | 100 / min |
| `PUT` | `/Users/{id}` | Replace all attributes of an existing user (used by Microsoft Entra ID). | 100 / min |
| `PATCH` | `/Users/{id}` | Apply partial updates to a user (used by Okta and most IdPs). | 60 / min |
| `DELETE` | `/Users/{id}` | Remove a user from the app. | 30 / min |
Pagination defaults: `count` defaults to `100` and is capped at `500` per request.
## Supported attributes
| SCIM attribute | Notes |
| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `userName` | Required on create. Used as the user's email. If absent, Softr falls back to the primary entry in `emails`. |
| `name.givenName`, `name.familyName`, `name.formatted` | Combined into the user's full name. |
| `displayName` | Takes precedence over `name.*` when resolving the full name. |
| `emails[].value` | The primary email is used as `userName` if `userName` isn't supplied. |
| `active` | `true` activates the user; `false` deactivates them. |
| `password` | Optional, write-only. Most IdPs do not send a password — Softr generates one automatically and the user sets their own via the invitation email. |
## Supported filters
The `GET /Users` endpoint supports a single filter form, which is what Okta and Entra ID send during user lookup:
```
GET /Users?filter=userName eq "user@example.com"
```
## Setting up SCIM in your IdP
The provisioning flow looks the same in every SCIM-capable IdP — only the UI differs. In your IdP's SCIM (or "User Provisioning") settings:
1. **Create or open the Softr app in your IdP**
Add Softr as a SCIM-enabled application in your IdP, or open the existing app you already use for SSO. SCIM is configured on the same application.
2. **Enter the SCIM Base URL and Bearer Token**
Paste the Softr **SCIM Base URL** (`https://studio-api.softr.io/scim/v2/applications/{applicationId}/Users`) and your Softr **API key** as the Bearer token.
3. **Verify the connection**
Use your IdP's built-in **Test Connection** / **Verify** button. It will issue a test request against Softr to make sure the URL and token are valid.
4. **Enable provisioning and assign users**
Turn on the provisioning actions you want (Create Users, Update Attributes, Deactivate Users) and assign the users or groups that should have access to the Softr app. Your IdP will start pushing them to Softr.
For provider-specific UI details, see your IdP's documentation:
- [Okta — Configure SCIM provisioning](https://help.okta.com/oie/en-us/content/topics/provisioning/scim/scim-app-integration.htm)
- [Microsoft Entra ID — Automatic provisioning with SCIM](https://learn.microsoft.com/en-us/entra/identity/app-provisioning/use-scim-to-provision-users-and-groups)
- [OneLogin — SCIM Provisioner](https://developers.onelogin.com/scim)
## Example requests
You can smoke-test the SCIM endpoint with `curl` before pointing your IdP at it.
### Create a user
```bash
curl --request POST 'https://studio-api.softr.io/scim/v2/applications/YOUR_APP_ID/Users' \
--header 'Authorization: Bearer YOUR_SOFTR_API_KEY' \
--header 'Content-Type: application/scim+json' \
--data-raw '{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "jane@example.com",
"name": {
"givenName": "Jane",
"familyName": "Doe"
},
"emails": [
{ "value": "jane@example.com", "type": "work", "primary": true }
],
"active": true
}'
```
### Deactivate a user
```bash
curl --request PATCH 'https://studio-api.softr.io/scim/v2/applications/YOUR_APP_ID/Users/USER_ID' \
--header 'Authorization: Bearer YOUR_SOFTR_API_KEY' \
--header 'Content-Type: application/scim+json' \
--data-raw '{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{ "op": "replace", "path": "active", "value": false }
]
}'
```
## Error responses
Errors follow the standard SCIM error schema (`urn:ietf:params:scim:api:messages:2.0:Error`). Common statuses:
| Status | Meaning |
| ------ | ------------------------------------------------------------- |
| `400` | Malformed request, unsupported PATCH path, or invalid filter. |
| `401` | Missing or invalid Bearer token. |
| `403` | SCIM is not enabled for this workspace's plan. |
| `404` | The application or user does not exist. |
| `409` | A user with the same email already exists in the app. |
## Limitations
Softr's current SCIM implementation supports:
- The `Users` resource only — `Groups` provisioning is not yet supported.
- `add` and `replace` PATCH operations.
- The `userName eq "value"` filter form.
Manage [user groups](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/user-groups/6XQfKMeKHUvBcAjKvLs3g3) inside Softr while SCIM keeps the underlying user records in sync.
---
# Microsoft Azure SAML Single Sign-on
Source: https://docs.softr.io/add-and-manage-users/microsoft-azure-saml-single-sign-on
[Microsoft Azure](https://azure.microsoft.com/en-us/) is a popular cloud computing platform that can be used to set up [SAML single sign-on](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/saml-single-sign-on/j9hELMUfGtAGqoNzejgoif) using its directory service called **Active Directory**. Let’s see how you can do that for your Softr app to let your users sign in with their Azure credentials.
## Creating an application
First of all, you need to create an application. To do that, navigate to **Enterprise Applications** on your Azure dashboard.

_Enterprise applications_
Then, hit **New Application**.

_New application_
Next, in the app gallery, search for **Azure AD SAML Toolkit** and select the app.

_Locating “Azure AD SAML Toolkit”_
In the sidebar that opens next, specify a name for your app and hit **Create**.

_Creating the application_
Now that you have your application, you need to set up single sign-on for it, which we’ll discuss next.
## Getting started with single sign-on setup
On the **Overview** screen of the application that you just created, click **Get started** under **Set up single sign on**.

_Getting started with single sign-on setup_
In the next screen, select the **SAML** method.

_Selecting the single sign-on method_
You’ll be taken to the configuration page, where you need to set up the required parameters in order to integrate the single sign-on with your Softr app.
## Basic SAML configuration
The first step of the setup is **Basic SAML Configuration**. Click **Edit** in the upper right corner to enter the configuration screen.

_Basic SAML configuration_
First comes the **Identifier (Entity ID)** property, which can be found under **Audience URL** in your Softr app’s **Settings ⇒ SAML Settings**. Just copy the value and paste it in Azure.

_Adding Entity ID_
Next, you need to add the **Reply URL (ACS URL)**, which can be located under **ACS URL** in your Softr app’s SAML settings. **The Index** field can be left empty.

_Adding ACS URL_
Lastly, you have the **Sign on URL**, which should have the URL of the page where your SSO login form is located.

_Softr application page with an SSO sign-in block_
You need to copy the URL and paste it under **Sign on URL** in Azure.

_Adding the Sign on URL_
To finalize the setup, hit **Save** and close the sidebar.
## Attributes & Claims
In this step, you need to copy the **First Name**, **Last Name**, and **Email** keys from Azure and add them into your Softr app’s single sign-on settings.

_Getting the keys from Azure_
The keys should be applied as shown in the following screenshot.

_Applying keys in Softr_
## SAML Certificates
In this step, you need to download the **Metadata XML file** in Azure.

_Metadata XML Download_
Next, open the file with any suitable editor, copy the entire content of the file, and add it to your Softr app under **SAML Settings**.

_Adding metadata XML to Softr_
And you’re almost done. There’s one last step remaining, which we’ll discuss next.
## Assigning users to an application and testing
Now, your users should be able to log into your Softr app with their Active Directory credentials. **Note, that the user needs to be assigned to your Azure application to be able to access it.** To assign a user, you need to navigate to the **Users and groups** sections of your application and add that user.
The following gif shows the process of assigning a user to an application.

_Assigning a user to your application_
The assigned user should now be able to log into your Softr app through single sign-on.

_Signing in with Active Directory credentials_
---
# User Groups
Source: https://docs.softr.io/user-groups-and-permissions/user-groups
User groups are an essential part of delivering a personalized experience and showing the right information to your users. In addition to making blocks and pages accessible to logged-in or non-logged-in users, Softr allows you to create custom user groups.
Let's start with how user groups are created.
> **Tip**
>
> Note that in order for changes to user groups to take effect, the application needs to be [published](/publishing/9qTmU2Lj8Gnpr1Ue6dEAkX/publishing-your-softr-app/gRrb1u7eLmRTrXyg3UNGkQ) after making the changes.
## Create a user group
To create a user group, open the **Users** tab and go to **User groups**. Then click **Add custom group**.

_The User groups list: built-in groups, your custom groups, and the Add custom group button._
In the **New user group** window, enter a name. Then choose how to assign users: **Manual** or **Condition-based**.

_The New user group window\._
Click **Save** when you are done. Learn how to add users below.
## Add users to your user group
Once you have a user group, you need to add users to it. You can do this manually or by adding users based on their attributes with conditions.
### Add users manually
To add users manually, select **Manual**. Then select one or more users from the list.

_Select the users of the group from the list._

_The selected users show as chips._
You can also manually assign a user group to a user from the users table.

_Add users manually directly from the users table_
### Add users based on a condition
Select a logged-in user's attribute and specify a relevant condition and value.
> **Info**
>
> You can learn more about using conditional filters here → [Conditional Filters](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/conditional-filters/mDnn7jnpPiYmJcT99jpt7m)
You can also specify conditions based on payment-related attributes, such as one-time products and subscriptions. To use these attributes, you must connect Stripe to your application. [Learn how to add users based on their Stripe attributes](/how-to-guides/ioi5BbuQ2RDM7aHPrpXnjG/add-users-to-user-groups-based-on-stripe-attributes/g1A2tEtjvmiCtGL1hgJmMe).

_A condition-based group: set the attribute, the condition, and the value._
## **Manage user groups for each user from the users table**
A user's user groups are visible in the users table. You can see which user groups they're in, and you can assign and remove any user group they were added to manually.
However, you cannot remove a user from a user group they were added to based on a condition. This is because of the rule yourself or a collaborator set up when creating the user group. To edit the conditions for a user group, go to the user groups tab and edit the condition(s) used to add users.


## Set block and page visibility for your user group
Once you've created a user group, you can use it to control who can see a particular block or page.
To set block visibility, go to the block's visibility settings, select Logged-in users, and select the relevant user group from the dropdown list.
To set page visibility, go to the page's settings, select Logged-in users, and select the relevant user group from the dropdown list.
Now, only users in the selected user group will be able to see the block or page.

_Setting block visibility for a user group_
## Set advanced action permissions for your user group
You can also use user groups to control who can perform specific actions on a block.
To do this, go to the relevant block and open the Button visibility settings from the Actions tab. From there, you can define which user groups should be able to see and interact with the action.

_Open action button visibility settings_

_Select the user groups that can see and interact with this button_
## Edit, reorder, or delete a user group
Open the **Users** tab and go to **User groups**. Hover over a custom user group to see its actions.
- Click the pencil to edit the group.
- Click the bin to delete the group.
- Drag the handle on the left to change the order of your custom groups.

_The actions of a custom user group._
## Security
> **Tip**
>
> Softr viability checks and record conditional filters are applied on the server side, and there is no way to trick the system. Learn more about [Softr App Security](/security/ummZ2CWNHXZCHzsZwbEwET/softr-app-security/1xC7Hgkvo67AnHKyebr1uC).
---
# Conditional Filters
Source: https://docs.softr.io/user-groups-and-permissions/conditional-filters
Conditional filters show only the records that meet the conditions you define. They work on the List block and on other dynamic blocks.
> **Info**
>
> Conditional filtering is also used when you want to display a main list of items, and upon selecting a specific item, show its details along with its associated sub-items. Learn about [Linked List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/linked-list/bWjTdKhbftofSEKRSxMFz9).
In the Studio, this section is called **Record filters**. Find it in the **Source** tab of the block settings. See also [Record filters](/user-groups-and-permissions/record-filters).

_The Record filters section in the Source tab of a block._
First, use the dropdown at the top to choose whether **any** or **all** of the conditions must be met.

_“Any” or “All” of the conditions_
Extra conditions join with:
- AND (when "All" is selected)
- OR (when "Any" is selected)

_The second condition starts with And when “All” is selected._
Each condition has three parts: a field, a condition, and a value.
## **1. Field**
Select the field of the data source table that the condition tests.
## 2. Condition

_The conditions available for a text-like field._
The condition describes how the field relates to the value. The available conditions depend on the field type.
**Text-like fields**, such as emails, formulas, URLs, and single select fields, can be used with the following available conditions:
- **Is** – the Field value needs to match the Valueexactly
- **Is not** – the Field value has any value apart from the Value
- **Contains** – the Field value partially matches the Value
- **Does not contain** - the Field value doesn’t partially match the Value. It checks if the given Value is not present within the Field value
- **Is any of** –the Field value is any of the Value(s). Multiple values can be added
- **Is none of** – the Field values have any other value apart from the Value(s). Multiple values can be added
- **Is empty** – the Field value is empty
- **Is not empty** – the Field value is not empty. Has some value
- **Starts with** – the Field value starts with the Value
- **Ends with** – the Field value ends with the Value
**Numeric fields** can be used with the following available conditions:
- \=
- ≠
- \>
- \<
- ≥
- ≤
- Is between _(inclusive of min/max)_
- Is empty
- Is not empty
**Array-like fields**, such as multi-select fields, linked records, tags, and lookup fields, can be used with the following available conditions:
- Includes any of
- Includes all of
- Includes exactly
- Includes none of
- Is empty
- Is not empty
**Boolean fields**, such as checkbox fields:
- Is
- Is not
- Is empty
- Is not empty
> **Info**
>
> Date fields currently use the same conditions as text-like fields.
## 3. Value
You have two options.
### Entering a specific value
Enter a value. The block then shows only the records that have that value.
> **Tip**
>
> If the **value contains a space**, you'd need to copy it from somewhere else instead of typing it in.
For example, a Tasks table in [Softr Databases](/softr-databases/softr-databases-overview) has a Status field. To show only the tasks in progress, set the condition to **Status is In progress**.

_A Tasks table with Task, Details, Status, Priority, and Assignee email fields._
### **Using Logged-in user's parameters**
Use this option to filter the block for each logged-in user, so that each user sees only their own records.
By default, you can use the user's **Email** and **Email domain**. If you've [connected users to a data source](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/syncing-users-with-a-data-source/hshRGygHr4T33EnaLntGf9), all the fields of that data source are available too.
Here is an example. The Tasks table has the fields **Task**, **Status**, and **Assignee email**. The Assignee email field holds the email of the user who owns the task.
Each user should see only their tasks. One condition does this. Set the **Field** to **Assignee email** and the value to the **logged-in user's Email**. The block then shows only the tasks where Assignee email matches the email of the user who is logged in.

_One table and one condition give each user a different view\._
You can set a condition like this for any field of your block.
> **Tip**
>
> Softr plans to add more user attributes for filtering, such as user roles and statuses.
### Use Case: **Using a Checkbox field in a Conditional Filter**
You can filter on a Checkbox field.
> **Tip**
>
> The List block can't display a Checkbox field (the [Table](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/table-block-/j7rGwu7J7zuU69h3bZ7HFe) block can). You can still use it in a conditional filter without displaying it.
To show the records with the checkbox checked, use the **is not empty** condition. To show the unchecked records, use **is empty**.

_“is not empty” shows the checked items._
## Security
> **Tip**
>
> Softr applies visibility checks and record filters on the server side, so users cannot bypass them. Learn more about [Softr App Security](/security/ummZ2CWNHXZCHzsZwbEwET/softr-app-security/1xC7Hgkvo67AnHKyebr1uC).
---
# Record Filters
Source: https://docs.softr.io/user-groups-and-permissions/record-filters
## Overview
Record filters refer are [conditional filters](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/conditional-filters/mDnn7jnpPiYmJcT99jpt7m) you can apply on dynamic blocks (e.g., List, Table, Grid, Kanban) to control which records from a data source are displayed.
Record filters are simply one area where conditional filtering can be applied. To learn more about conditional filters and where they can be applied, check out the [Conditional Filters doc](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/conditional-filters/mDnn7jnpPiYmJcT99jpt7m).

_Where to set record filters: the Source tab of a dynamic block._
## Key Use Cases
There are a few ways in which you can use conditional filtering to only show specific record(s) on a block. Note that this filtering is not accessible to the end user and essentially pre-filters the list or items for them to only see a specific record or set of records.
- **Basic Filtering**: Display only records meeting static criteria, such as tasks in a specific status (e.g., "In Progress") or events in the current year (e.g., date field is after a certain date). This is ideal for curating views without user input and acts as a sort of pre-filter.
- **Show records relevant to the current user**: Show items relevant to the logged-in user, like tasks assigned to their email (e.g., ‘Assignee’ field is Logged-in user’s Email). This personalizes the experience and enhances security by hiding irrelevant data.
- **Integration with Global Data Restrictions**: Global data restrictions apply app-wide rules first (for example, restricting a user group to view only certain records), and record filters layer on top for block-specific refinements. They work together seamlessly: global data restrictions enforce broad access controls, while record filters handle granular display logic within allowed data. For example, if globals restrict a table to user-owned records, record filters can further narrow to a specific status.
Additionally, record filtering for specific user groups using global data restrictions can save you time by not having to manually apply record filtering to multiple blocks that show the same data.
- **Show only records relevant to current details page’s record**: In linked list setups, filter sub-items based on the selected main record (e.g., show tasks linked to the current project via a record ID match). This creates hierarchical views, like a project details page displaying only associated tasks.

_Example: a record filter that shows each logged-in user only the tasks assigned to their email._
## Tips and Tricks
- You can combine filters to create complex logic using “And” and “Or” type filtering to achieve the desired result. In the event you need cascading or sub-grouping of filters, a tab container can help by branching each block out into the needed sub-grouping.
---
# Action Button Visibility
Source: https://docs.softr.io/user-groups-and-permissions/action-button-visibility
> **Tip**
>
> Button visibility options depend on the subscription plan:
>
> → On Free and Starter plans you can decide who can see the button (All Users, Logged-in Users, or Non Logged-in Users)
>
> → On Professional plan you can also configure conditional visibilitybut can’t set [custom user groups](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/user-groups/6XQfKMeKHUvBcAjKvLs3g3).
>
> → On Business plan you have access to all the features in Button Visibility.
>
> → Not all Action buttons can be configured to be visible for non-logged in users. For example, Edit, One-click Update, and Delete cannot be shown to visitors.
>
> See [plan comparison](https://www.softr.io/pricing).
Each [Action Button](/actions/ntEfT9zSJk6aY54G6W5KGU/action-buttons-overview/idg8Fqf2kjFwcx6kyP3jNq) has a **Button Visibility** section where you can define which users the button is accessible to.

_Accessing Button Visibility_
**Topbar buttons** such as the [Add Record](/actions/ntEfT9zSJk6aY54G6W5KGU/add-record/3LrUMpQY4BKfDDQj6eb8h8) button have only the **Who can see** section, where you can choose between **all users**, **logged-in users** and **non logged-in users** as well as select a specific [user group](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/user-groups/6XQfKMeKHUvBcAjKvLs3g3), so that the button is visible only to the selected custom user group.
**Item buttons** (such as the [Update Record](/actions/ntEfT9zSJk6aY54G6W5KGU/edit-record/irSJXPF1gCMXNmfsQFscvx) button), on the other hand, also have an option to set conditional visibility (called **On which record**) to show selected records based on conditional rules.
> **Tip**
>
> The **conditional visibility** works similar to [List Conditional Filters](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/conditional-filters/mDnn7jnpPiYmJcT99jpt7m).
We set up button visibility when configuring [Add Record](/actions/ntEfT9zSJk6aY54G6W5KGU/add-record/3LrUMpQY4BKfDDQj6eb8h8) and [Update Record](/actions/ntEfT9zSJk6aY54G6W5KGU/edit-record/irSJXPF1gCMXNmfsQFscvx) buttons, so you can check out these articles for specific examples of customizing button visibility.
---
# Block Visibility
Source: https://docs.softr.io/user-groups-and-permissions/block-visibility
This section goes through the process of configuring the visibility of any block in your Softr app.
As soon as you have set up memberships, you can choose which user group you want a particular block to be visible to. This is configured through **Visibility** tab in block settings and has the following options:
- **All users** (selected by default)
- **Logged in users**
- **Non Logged in users**

_Visibility options_
If you switch the block visibility to **Logged in users** or to **Non Logged in users**, a padlock icon will start appearing on the block, as shown below, indicating that it's gated content with limited visibility.
> **Tip**
>
> Please, keep in mind that gated content (e.g. blocks that are only accessible to logged-in users or a specific group of users) will not be crawled by search engines.

_Padlock icon indicating limited visibility_
For example, the block visibility feature can be used to show a header with log-in/sign-up buttons to non-logged-in users and a different header without buttons to logged-in users (discussed [here](/11ba304436ed4354a8669d4869624b9c)). But that's just one case, and there can be many other cases when you need to display/hide a certain block from a different user group, thus having different content for logged-in and non-logged-in users.
## **Device visibility**
Apart from setting block visibility for certain user groups, you can set device-based visibility.

_Device visibility options_
By default, **Desktop**, **Tablet**, and **Mobile** options are enabled. You can disable any of the options by clicking on it. In the example below, only logged-in users who are viewing the page on a mobile device will see the block.

_Applying device visibility_
## **Custom user groups**
You can also define more low-level visibility rules for custom user groups. Learn more about [User Groups](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/user-groups/6XQfKMeKHUvBcAjKvLs3g3).
## Security
> **Tip**
>
> Softr viability checks and record conditional filters are applied on the server side, and there is no way to trick the system. Learn more about [Softr App Security](/security/ummZ2CWNHXZCHzsZwbEwET/softr-app-security/1xC7Hgkvo67AnHKyebr1uC).
---
# Page Visibility
Source: https://docs.softr.io/user-groups-and-permissions/page-visibility
Page visibility can be used when you want to restrict a certain page to just **Logged in users** or just **Non Logged in users.** It is configured in [Page Settings](/0392ff65acfe4b1c96923c1aac7982f7) => **Visibility** and has the following options:
- **All users** (selected by default)
- **Logged in users**
- **Non Logged in users**

_Page visibility options_
This functionality can be used to have gated content on your Softr app, allowing only logged in users to view specific pages. [Here](/how-to-guides/ioi5BbuQ2RDM7aHPrpXnjG/how-to-create-a-membership-site/diSie6ZE72tDDvrfBkmcmm), we've shown how it can be used to make the page with online courses accessible to logged in users only.
> **Tip**
>
> Please, keep in mind that gated content (e.g. pages that are only accessible to logged-in users or a specific group of users) will not be crawled by search engines.
## Custom User Groups
The **User Groups** settings for the page are similar to [that of the block](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/user-groups/6XQfKMeKHUvBcAjKvLs3g3) but allow setting access for the whole page.
---
# Page Rules
Source: https://docs.softr.io/user-groups-and-permissions/page-rules
## Benefits of using Page Rules
With Page Rules, you can use your defined [User Groups](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/user-groups/6XQfKMeKHUvBcAjKvLs3g3) to route users to different pages based on which user group(s) they are a part of. This is helpful when you need to control the flow of users through your app. When combined with block level visibility, Page Rules allow for complex user onboarding flows, user approval processes, and even subscriber page routing.
## How do I use Page Rules?
To access Page Rules, click on the Page Tab, then click on the Pages Rules button.

_Click on page tab, then the Page Rules link_
On the Page Rules screen, you have several options to configure, depending on your number of users groups.

1. You’ll see all of your User Groups listed. You can think of **Logged-in User** as a fallback rule for any user that does not fit into a user group. If a user falls into multiple user groups, the groups at the top of the list take precedence. You can think of the list of group as a heirarchy and adjust them in the stack by dragging and dropping the handle to the left of the user group’s name.
2. Depending on what the user is doing, you can define the page they are taken to based on these columns - After sign-in, sign-up, and sign-out. For pages users are not allowed to see, they will always be taken to the [Permission Denied Utility page](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/permission-denied-401/54HYs3JEk1EoiwpFbPzVSF).
3. In each dropdown, you can choose which page the user should be taken to after the action in the column. By default, all user actions take them to the Home Page.
## **Which signin/signup options are supported?**
As of now, the user group redirects are applied to all the signin/signup options **apart from the following ones:**
- [SAML Single SIgn-On](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/saml-single-sign-on/j9hELMUfGtAGqoNzejgoif)
- [OpenID](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/openid-single-sign-on/hqqStep7RUmiSMb6qnGLkq)
---
# Global data restrictions
Source: https://docs.softr.io/user-groups-and-permissions/global-data-restrictions
Global data restrictions hide irrelevant or sensitive records across dynamic blocks, dropdown options, and inline filters. You set a rule once, and it applies to the whole app. Your users see the records they need and nothing else.
> **Tip**
>
> Global data restrictions are not available for the Comments block.
Client portals are a common use case. They restrict each client to their own data, which protects privacy and blocks access to other clients' information.
> **Note**
>
> “View” data restrictions are available on all plans, including Free.
> ”Create”, “Edit”, and “Delete” data restrictions are available on the [Business plan and above](https://www.softr.io/pricing).
## Getting started
To open global data restrictions, open your app in the Studio, go to the **Users** tab, and open **Data restrictions**. This tab lists every restriction in your app. Click **Add restriction** to create one.

_The Data restrictions tab lists each rule with its table, user groups, and restriction types._
## Adding a restriction
### Select a source to define restrictions
A restriction rule applies to one table in your data source. Select the source as you do when you connect a block. Use the “Used in this app” toggle to list only the sources your app already uses.
### Apply restrictions to
A restriction rule can apply to one or several user groups. You cannot apply a restriction to a single user, unless that user is alone in a user group.
### Specifying restriction types & scopes
**Restriction types**
A restriction is made up of restriction types.
| | |
| ------ | -------------------------------------------- |
| Type | Description |
| View | Restrict what users can only or can’t see |
| Create | Restrict users from creating new records |
| Edit | Restrict what users can only or can’t edit |
| Delete | Restrict what users can only or can’t delete |
Choose one or all of these restriction types. The rules then apply to the table and the user groups you selected.
> **Info**
>
> By default, your users are unrestricted. They can view, create, edit, and delete records, unless a block-level setting says otherwise. Each restriction you add narrows the data your users can reach.
**Restriction scopes**
A restriction also contains one of two scopes.
| | |
| -------- | ------------------------------------------------------------------------------------------------------------------------- |
| Scope | Description |
| Can only | Specifies the records that users **can** take any of the available actions on (viewing, creating, editing or deleting). |
| Can’t | Specifies the records that users **can’t** take any of the available actions on (viewing, creating, editing or deleting). |
> **Note**
>
> When a user belongs to several user groups with conflicting rules, “Can’t” restrictions take precedence.
For example: Table X has 5 records: A, B, C, D, E and the following restriction rules applied:
| | |
| ---------- | ---------------------------- |
| User group | Restriction rule |
| A | Can only view record A, B, C |
| B | Can only view record D, E |
| C | Can't view record E |
Result: A user in all three user groups can view records A, B, C, and D.

_The same example: A, B, and C come from group A, D comes from group B, and group C hides E._
**Adding conditions**
Add conditions to link records to the table and user group. For example, to let User group A view only its own records in Table W, match the logged-in user's email to the Email field of Table W. Each user then sees only the Table W records with their email.

_Restrict view access to Table W's records for User group A based on email_
## What your app users see
This table shows how global data restrictions change what your app users see.
| | | | | | | |
| ------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| Type | Scope | Action buttons | Dropdown field options | Inline filters | **Customizable forms** | Dynamic block records |
| View | Can only view certain or all records | N/A | App users **will only** be able to see the dropdown options for records specified by restriction rules. | App users **will only** be able to see the options for records specified by restriction rules (i.e if there is a “Status” inline filter, and only “Done” & “In Progress” items are visible, then only display the Done & In Progress filters). | N/A | App users **will only** be able to see the options for records specified by restriction rules (same behavior as conditional block filter). |
| View | Can’t view certain or all records | N/A | App users **will not** be able to see the dropdown options for records specified by restriction rules. | App users **will not** be able to see the options for records specified by restriction rules (i.e if there is a “Status” inline filter, and all “ToDo” items are restricted, then don’t display the ToDo filter). | N/A | App users **will not** be able to see the options for records specified by restriction rules (same behavior as conditional block filter). |
| Create | Can’t add records | App users **will not** be able to see any configured add record action buttons used in blocks connected to the restricted table. | N/A | N/A | App users **will not** be able to submit form entries. They still see a submit button, but it is disabled. | N/A |
| Edit & Delete | Can only edit/delete certain or all records | App users **will** see the configured edit, update, or delete action buttons for the records that the restriction rules allow. | N/A | N/A | N/A | N/A |
| Edit & Delete | Can’t edit/delete certain or all records | App users **will not** be able to see any configured edit, update or delete action buttons for the records specified by restriction rules. | N/A | N/A | N/A | N/A |
## Adding more than one restriction to a table
You can add several restriction rules to a table. Each combination of table and user group can appear only once. This limits conflicting rules.
For example, a rule on the Full-time table already applies to the HR user group. You can add another rule to the Full-time table, but you cannot select HR again. To use HR in the new rule, first remove it from the existing rule.

_HR is not selectable because another rule on this table already uses it._
---
# Options Filters
Source: https://docs.softr.io/user-groups-and-permissions/options-filters
## Overview
Options filters are a specialized use of [conditional filters](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/conditional-filters/mDnn7jnpPiYmJcT99jpt7m) to restrict the choices available in dropdown inputs, conditional forms, or similar selection fields, ensuring users only see relevant options based on conditions.
## Where Can Options Filters Be Used?
- **Dropdown Inputs**: In forms for creating or updating records, to filter options in linked record or value-based dropdowns.
- **Quick Select Inputs**: You can filter a quick select field in conditional forms to only show options that meet certain criteria.
- **Inline Filters**: On dynamic blocks, where user-facing filter dropdowns can have their options restricted (e.g., only show filterable statuses that the user has access to).
- **Other Contexts**: Any selection field mapped to a data source, such as in conditional forms for step or section logic.
## Why Use Options Filters?
Options filters improve user experience by preventing irrelevant or unauthorized selections. For example, clients can only see and select projects relevant to them in a dropdown (for example, filter by client email matching the Logged-in user’s Email), This can help dramatically in reducing errors and keep people from seeing options they shouldn’t see.
## How Options Filters Work with Global Data Restrictions
Global data restrictions apply first to limit the overall data (e.g., hiding restricted records from the data source table), and options filters then refine the visible choices within that selection. For instance, if global data restriction rules restrict a projects table to user-owned records, options filters can further limit dropdown options to active projects only. This layered approach ensures security at the app level while allowing precise control in inputs.
---
# Application Theme
Source: https://docs.softr.io/styling/application-theme

_Theme section_
In the **Theme** section, you can set the default styles and colors for all the building blocks and then customize them for each block separately (from block’s [Styles and Colors settings](/styling/7qXYEkNvWQamR6vcLXzZnF/block-styles-and-formatting/dy4vuKjHgksR4pDJLFKAHP)) if needed.
First comes the **Base Text Size**, which will correspond to the **“m”** size in the individual text field settings. For instance, if you've selected the **Base Text Size** as "16px", the **"m"** **Text Size** in block settings will correspond to 16px, and the other sizes ("s," "l," and so on) will work accordingly.

_Changing font size in Block Settings_
Next you can set the default **Font Family**, **Font Weight**, and **Color** for your Header (titles) and Body (subtitles and the rest).
Further on, you can set the default **Text Size**, **Text Color**, and **Background Color** for your **buttons**.
Finally, we have the **Advanced** section, where you can set the **Website width**.

_Advanced section_
You can set the width to **Fixed** (controlled by you), **Full** (to occupy the full width of the screen), or define a **Custom width** (should be at least 1140px).

_The process of configuring the Theme_
---
# Block Styles and Formatting
Source: https://docs.softr.io/styling/block-styles-and-formatting
Each [block](/97425386980f42deaf4a77dd07b346a9) has a **Styles** tab in the settings sidebar, which you can use to apply custom styling and colors to the block. Let’s review some of the common settings that most of the blocks have.
## ****Background Color****
This is for setting the background color of the entire block.

_Block background color_
## ****Padding****
Allows to control the **Top** and **Bottom** **Padding** within the block, as shown below.

_Adjusting top and bottom padding_
## ****Border****
Here you can add a top and bottom border to the block and apply custom border **Style**, **Width**, and **Color**.

_Adjusting border_
> **Info**
>
> You can also use custom CSS code for more advanced styling use cases. [Learn about custom code](/custom-code/3idxDhKqz1qPdqBuWbs61G/custom-code-block-overview/6XNrxFopUEiwbWipq81Eq1).
---
# Publishing Your Softr App
Source: https://docs.softr.io/publishing/publishing-your-softr-app
Publishing the application pushes all your changes to the web instantly. Your application and all pages in [Studio](https://studio.softr.io) are not visible to anyone before you publish and share a link.
By default, your application gets assigned a random subdomain: **https\://\.softr.io** and is published to the **Staging** environment of Softr (not visible to anyone except you). You can view domain and publication status info by clicking the **Publish** button on the top navigation bar.

_Random Softr subdomain and Published status_
When you want your application to be visible to anyone on the web, you need to publish your changes to the **Live** environment and share a link. You can do this by clicking the Publish button inside the pop-up.

_Publish button_
After publishing, you can share the public subdomain link to anyone (e.g. **""** from the example above). In the next section, you'll find out how to personalize your subdomain link.
## Previewing your Softr app
Softr also has an option to Preview the app before publishing to see how it works and what it looks like. You can even preview the app as specific users of your application to see exactly what a user or group of users will see on their side. To preview your Softr app, click on the Play icon in the upper right of Softr Studio.

_Click on the play button to start the preview_
With the preview open, you can use the dropdown in the upper left to search and select the user you would like to preview as. You can also generate a shareable preview link using the **Get shareable link** button in the upper right of the preview window so that others can preview your application if needed. Use the device selector in the top-middle of the screen to preview your app on different device screen sizes.

## Previewing with QR Code
You can also easily preview the tablet and mobile versions of your app by scanning the QR code that is available when previewing those devices in the Softr Preview. Simply select tablet or mobile view at the top of the preview window and scan the QR code with your device.
Alternatively, you can also email a link to preview the app to your Softr account email.

## Custom Subdomain
You can customize your public subdomain that is assigned randomly (**https\://\.softr.io)** to **""**. You can do this from the Publish dropdown as shown below.

_Editing the subdomain_
You can also connect your custom domain (e.g. **yourdomain.com**). For more information, please refer to the [Custom Domain](/publishing/9qTmU2Lj8Gnpr1Ue6dEAkX/add-a-custom-domain-to-your-app/93K5bLJN3n91MRo9uRGdAf) guide.
> **Tip**
>
> Please, note that if you make any changes to your app content, settings, domain name, etc. after publishing the application, you need to **publish it again** for the changes to take effect.
---
# Unpublishing Your App
Source: https://docs.softr.io/publishing/unpublishing-your-app
You can easily unpublish your Softr app by clicking on the Settings tab in Softr Studio, then clicking on General.

Scroll to the bottom of the General settings options and click on Unpublish Application:

Click on Unpublish to confirm and unpublish the application. Note that your application will no longer be available on custom domains or Softr subdomains until you re-publish, but will always be available for Preview from within Softr Studio:

---
# Add a Custom Domain to Your App
Source: https://docs.softr.io/publishing/add-a-custom-domain-to-your-app
> **Note**
>
> All plans come with 1 custom domain included. Additional domains can be purchased as add-ons.
## Overview
Every Softr app gets a free Softr domain, for example `myportal.softr.app`. You can change it at any time in the **Publish** menu or in **Settings → General → Domains**.
You can also publish your app on a domain you own. Softr supports two kinds of custom domain:
- **Root domains**, for example `example.com`. Softr also adds `www.example.com` for you.
- **Subdomains**, for example `portal.example.com`.
Each app can have one custom domain. Each custom domain counts towards the custom domain limit of your workspace plan.
Softr uses [Entri](https://www.entri.com/) to set up your domain. Entri signs in to your domain provider and adds the DNS records for you, so you do not have to edit DNS settings yourself. If you prefer, you can still [add the DNS records manually](#add-the-dns-records-manually).
## Connect a domain you own
### 1. Start the setup
In your Softr app, go to **Settings → General**. In the **Domains** section, click **Connect** next to **Custom domain**.
You can also start from the **Publish** menu: click **Add custom domain**.

_The Domains section in General settings_
### 2. Enter your domain
Enter the domain you want to use, for example `example.com` or `portal.example.com`, then click **Continue**. Softr detects if it is a root domain or a subdomain.

_Enter the domain you want to connect_
### 3. Continue to Entri
Softr shows the domain you are about to connect. Click **Continue** to open Entri. Click **Back** to change the domain.
Softr saves the domain on your app when you click **Continue**. If you close Entri before you finish, the domain stays in your settings and you can finish the setup later.

_Softr uses Entri to set up your domain_
### 4. Sign in to your domain provider
Follow the steps in Entri. Entri finds your domain provider (for example GoDaddy, Namecheap, or Cloudflare), asks you to sign in, and adds the DNS records that Softr needs.
> **Tip**
>
> If someone else manages your DNS, for example your IT team, Entri can send them a link so they can finish the setup for you.
### 5. Wait for the DNS changes
When Entri is done, you go back to Softr. The domain shows a loading icon while the DNS changes take effect. This can take up to a few hours.

_The domain waits for the DNS changes_
When the domain shows a green check mark, it is connected.

_A connected domain_
### 6. Publish your app
Click **Publish** in the top navigation bar. Your custom domain shows in the **Publish** menu. Click **Publish** to launch your app on the domain.

_Publish your app on the custom domain_
SSL is installed automatically when the domain points to Softr and the app is published.
## Buy a new domain
If you do not have a domain yet, you can buy one without leaving Softr.
1. Go to **Settings → General → Domains**.
2. Under **Custom domain**, click **Buy a domain**.
3. Search for a domain and complete the purchase in Entri.
Entri registers the domain and sets up the DNS records as part of the purchase. Softr then adds the domain to your app. Publish your app to launch it on the new domain.
> **Note**
>
> You need a free custom domain slot before you buy a domain. If your workspace has used all its slots, Softr asks you to upgrade your plan or add an extra domain slot first.
## Check the domain status
The **Domains** section shows the status of your custom domain next to its name.
| Status | What it means |
| ---------------- | --------------------------------------------------------------------------------------- |
| Loading icon | The DNS records are set up and waiting to take effect. This can take up to a few hours. |
| Green check mark | The domain is connected. |
| Warning icon | Softr cannot find the DNS records for the domain. |
Click the refresh icon next to **Custom domain** to check the DNS records again.
If Softr cannot find the DNS records, a warning shows above the domain. Click **Run setup** to open Entri again for the same domain.

_Softr cannot find the DNS records_
## Add the DNS records manually
You do not have to use Entri. After you enter your domain in Softr, the **Domains** section shows the DNS records your domain needs. Add them yourself in your domain registrar's or DNS host's dashboard. Click the copy icon next to a value to copy it.
Every DNS host has its own way to update DNS settings. Read the help documentation of your DNS host if you are not familiar with it. Also see our [FAQ](/faq/jUGRWwEkWw4akSEa5z5EDn/domain-setup/hZQgTBnTWKi7KEjurVHqgd) on domain setup.
> **Warning**
>
> Do not edit existing records in your DNS. **Add new records** for your Softr app.
### Root domain
For a root domain such as `example.com`, add an **A record** and a **CNAME** record:
| Type | Host | Value |
| ------------ | ----- | -------------------------------------------------------------------------- |
| **A record** | `@` | the IP address shown in the **Domains** section, currently `35.158.87.123` |
| **CNAME** | `www` | your own root domain, for example `example.com` |
> **Warning**
>
> The **CNAME** record's **Value** is your own root domain, `example.com`, **not** `@`. Registrars use `@` as shorthand for the root domain in the **Host** column only. It is not a valid CNAME value.
### Subdomain
For a subdomain such as `portal.example.com`, add one **A record**:
| Type | Host | Value |
| ------------ | --------------------------------------------------- | -------------------------------------------------------------------------- |
| **A record** | the subdomain part of the URL, for example `portal` | the IP address shown in the **Domains** section, currently `35.158.87.123` |

_The DNS record for a subdomain_
> **Tip**
>
> If you already own a domain, you can add as many subdomains as you like with your provider for free. Each custom subdomain you connect still counts towards the custom domain limit of your Softr plan.
> **Tip**
>
> **EXAMPLE:** See our example tutorial for a Namecheap subdomain setup [here](/publishing/9qTmU2Lj8Gnpr1Ue6dEAkX/tutorial-how-to-set-up-a-custom-subdomain-for-namecheap/3xKMZspFwCRukmmLYE649b).
## Remove a custom domain
In **Settings → General → Domains**, click **Remove** next to **Custom domain**, then click **Remove connection**. Your app is no longer available on that domain. The DNS records stay with your domain provider until you delete them there.
## Troubleshooting when a domain does not work correctly
If your domain is not working correctly after a few hours:
- Click **Run setup** in the **Domains** section to run the Entri setup again.
- The **CNAME** record should point to your custom domain, not to `{domain}.softr.app`.
- If your domain registrar does not allow `@` in the **A record** host, leave the host empty, and use **www** for the **CNAME** host.
- SSL is installed automatically once the domain points to Softr **and** you [publish the app](/publishing/9qTmU2Lj8Gnpr1Ue6dEAkX/publishing-your-softr-app/gRrb1u7eLmRTrXyg3UNGkQ).
If your DNS settings are correct and you still have issues after 48 hours, contact your domain provider's support, or contact us and we'll assist.
## FAQ
Below are some common questions we get about custom domains. Click the toggle to reveal each answer.
**What is Entri?**
[Entri](https://www.entri.com/) is a service that connects to your domain provider and sets up DNS records for you. Softr uses it so you can connect or buy a domain without editing DNS settings yourself. When you click **Continue**, you agree to Entri's [Terms of Service](https://www.entri.com/terms-of-service) and [Privacy Policy](https://www.entri.com/privacy-policy).
**Do I have to use Entri?**
No. You can [add the DNS records manually](#add-the-dns-records-manually) in your domain provider's dashboard.
**I already have a website, but I want to publish my Softr app to a custom domain, what should I do?**
If your website is website.com, the most common approach is to add a subdomain to Softr like portal.website.com or app.website.com. This ensures they share the same top-level domain, while having distinct URLs based on their purpose. Many web apps you use every day do this as well.
**My app says that the connection is not secure, what should I do?**
If you have waited 24 hours and you still cannot access the app, try these steps:
- Check the website URL in to see any issues.
- Make sure you have the right DNS records with the right IP address: **35.158.87.123**
- Try removing the domain from Softr and adding it again to re-initialize the SSL certificate.
- Make sure the app is published.
- Be sure to allow cookies for your site in your browser.
**Will a subdomain overwrite the site I have on my top-level domain, or vice versa?**
No, subdomains and top-level domains are handled differently and are seen as separate sites by the DNS.
**What if I'm using Cloudflare with Softr for DNS/SSL?**
If you are using Cloudflare with Softr, use **DNS Only** records instead of **Proxied** ones. See the image below.

**Can I enable DDOS protection on my site?**
Softr provides DDOS protection built-in to our servers.
**Can I self-host my Softr app on my own server?**
No, we do not currently offer self-hosting.
---
# Tutorial: How to set up a custom domain for Namecheap
Source: https://docs.softr.io/publishing/tutorial-how-to-set-up-a-custom-domain-for-namecheap
> **Note**
>
> Custom domain and extra custom domain slots depend on the subscription plan. See [plan comparison](https://www.softr.io/pricing).
1. First, log in to your [Namecheap account dashboard](https://www.namecheap.com/myaccount/login/).

2. Next to the domain you want to point to Softr, click on **“Manage”**.

3. Click into the **“Advanced DNS”** tab. If you see **CNAME Record** and **URL Redirect Record** with parkingpage.namecheap like values please delete them.

If your screen doesn’t look like the image above, it’s most likely because you have your DNS pointed elsewhere. In other words, to create DNS records at Namecheap, you need to be using **“Namecheap BasicDNS”** which is included with every domain. You can check by going into the **“Domain”** tab.
4. Click into the **“Advanced DNS”** tab and then click on “**Add New Record”.** If you see an A Record that already exists you will simply need to edit it (skip to the next step).

5. Add the two DNS records below. Softr shows you exactly what to create for your domain under **Settings → General → Domains**, once the domain has been added there.
| Type | Host | Value |
| ------------ | ----- | ------------------------------------------- |
| A Record | `@` | the IP address Softr shows you |
| CNAME Record | `www` | your root domain, for example `example.com` |

_Softr lists the exact records to create. Copy the Value column across to Namecheap._
> **Warning**
>
> In the **CNAME** row, the **Value** is your own root domain — for example `example.com` — **not** `@`. Namecheap uses `@` as shorthand for the root domain in the **Host** column, but it is not a valid CNAME value.
DNS changes can take a few hours to take effect.
---
# Tutorial: How to set up a custom subdomain for Namecheap
Source: https://docs.softr.io/publishing/tutorial-how-to-set-up-a-custom-subdomain-for-namecheap
1. First, log in to your [Namecheap account dashboard](https://www.namecheap.com/myaccount/login/).

2. Next to the domain you want to point to Softr, click on **“Manage”**.

3. Click into the **“Advanced DNS”** tab. If you see **CNAME Record** and **URL Redirect Record** with parkingpage.namecheap like values please delete them.

If your screen doesn’t look like the image above, it’s most likely because you have your DNS pointed elsewhere. In other words, to create DNS records at Namecheap, you need to be using **“Namecheap BasicDNS”** which is included with every domain. You can check by going into the **“Domain”** tab.
4. Click into the **“Advanced DNS”** tab and then click on “**Add New Record”.** If you see an A Record that already exists you will simply need to edit it (skip to the next step).

5. A subdomain needs a single **A record** — no CNAME. Set its **Host** to the subdomain label on its own, and its **Value** to the IP address Softr shows you under **Settings → General → Domains**.
| Type | Host | Value |
| -------- | ------------------------------------------------------------ | ------------------------------ |
| A Record | the subdomain label only — `portal` for `portal.example.com` | the IP address Softr shows you |

_Softr lists a single A record for a subdomain, and its Host is the subdomain label on its own._
Then create that same record in Namecheap:

_The finished record in Namecheap’s Advanced DNS tab._
> **Note**
>
> Unlike a root domain, a subdomain needs no CNAME record. If you have also followed the [top-level domain tutorial](/publishing/tutorial-how-to-set-up-a-custom-domain-for-namecheap), do not copy its `www` CNAME across.
DNS changes can take a few hours to take effect.
**You are done!**
---
# Add an Extra Custom Domain to Your Workspace
Source: https://docs.softr.io/publishing/add-an-extra-custom-domain-to-your-workspace
> **Note**
>
> Custom domain and extra custom domain slots depend on the subscription plan. See [plan comparison](https://www.softr.io/pricing).
If your [workspace](/workspace-and-billing/jZP6yaeXMiJCuB6HhS4xKd/workspaces-and-applications/kTbEWSYXhBCbtTB4K9dpKs) has exceeded the available number of custom domains, when you try to [connect a new custom domain](/publishing/9qTmU2Lj8Gnpr1Ue6dEAkX/add-a-custom-domain-to-your-app/93K5bLJN3n91MRo9uRGdAf) to your Softr app, you’ll see a pop-up with some details on the extra domain and a **Confirm** button.

_Adding an extra domain_
As soon as you click confirm, the additional fee will be added to your billing and you’ll be able to use the new custom domain.
---
# Softr SEO Checklist
Source: https://docs.softr.io/publishing/softr-seo-checklist
Softr has all the features that you need to optimize your application for search engines as well as monitor traffic, conversions, and more. Here’s a list of some of the key things you should consider for your Softr app in terms of SEO (Search Engine Optimization).
## 1. Tracking and reporting
[Google Search Console](https://search.google.com/search-console/about) is an essential tool for measuring your site performance as well as detecting issues. To set it up, go to your Google Search Console dashboard, navigate to **Settings => Ownership Verification,** choose the **HTML tag** option, and copy the value of **content** as shown below.

_Getting the verification tag_
Next, navigate to your [Softr app’s settings](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/general-settings/7YdGy1J8X2tjJSv8BGvWQU) and paste the tag under **Google Site Verification**. Hit **Save** and [publish your app](/publishing/9qTmU2Lj8Gnpr1Ue6dEAkX/publishing-your-softr-app/gRrb1u7eLmRTrXyg3UNGkQ), and you’re done.
Additionally, Softr offers integrations with such user analytics tools as [Google Analytics](/integrations/etS18kJqm1fuD58KCsjC3z/google-analytics/qt63nJLpVoXh7oyxJUVZL4), [Google Tag Manager,](/integrations/etS18kJqm1fuD58KCsjC3z/google-tag-manager/xn8tKtdvHywro9AipL7r53) and [Microsoft Clarity](/integrations/etS18kJqm1fuD58KCsjC3z/microsoft-clarity/dG1NQn87tXYYoJv7GRchym).
## 2. Page SEO
In page settings, you can configure **SEO Title and Description** to specify how your page appears in search results.

_How the page appears in Google search_
You need to make sure that your title and description fit the character limit. Google typically displays the first 50–60 characters of a title tag. Descriptions are limited to about 155 characters for desktop search and 120 characters for mobile search. There are also online tools such as [Mangool’s SERP Simulator](https://mangools.com/free-seo-tools/serp-simulator) that can help you with this.

_Page SEO settings_
Further on, you can control your page’s [indexing](https://growhackscale.com/glossary/indexing-seo#:~:text=What%20Is%20Indexing%20in%20SEO,to%20be%20displayed%20in%20SERPs.) as well as add a [Canonical URL](https://moz.com/learn/seo/canonicalization).
To see which pages on your site are in the Google index, you can do a Google Web Search for "site:mywebsite.com."
> **Tip**
>
> To speed up indexing your new website on Google, submit your sitemap in Search Console's [Sitemaps report](https://support.google.com/webmasters/answer/7451001). Softr creates your sitemap automatically, available at **yourdomain.com/sitemap.xml.**
## 3. Using the Custom Code section
There is a **Custom Code** section in every [page’s settings](/0392ff65acfe4b1c96923c1aac7982f7) as well as in your app’s [general settings](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/general-settings/7YdGy1J8X2tjJSv8BGvWQU). You can use it to add any sort of HTML or JavaScript (e.g. to integrate third-party tools that are not on the list of Softr’s integrations).
In particular, you can use the Custom Code section to add [structured data](https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data) in order to assist search engines in reading and categorizing the information on your page.
## 4. URL redirects
When we move pages to new destinations or delete them, it’s a common practice to apply a redirect from the obsolete URL to a new one to let users find the page, avoid 404 not found errors, forward the authority of the page to the new destination, and more. Using the **URL Redirects** feature in your [app settings](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/general-settings/7YdGy1J8X2tjJSv8BGvWQU), you can apply a redirect to any path on your app.
## 5. List Details SEO setup
The [List Details block](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/item-details-block-/4bE8XaFbJp45wkAwuWiz8f) works together with the [List block](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU) to display details for each item in the database. Since the List Details block occupies a single page on your Softr app and displays each database record’s details on the same page dynamically, you can’t really specify SEO parameters for each record using page settings. Therefore, Softr lets you configure SEO settings directly inside your [data source](/4230abecf813402aa2926466c313290a). Learn more on that [here](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/item-details-block-/4bE8XaFbJp45wkAwuWiz8f).

_Adding SEO parameters inside a data source_
## 6. Internal and External linking
Both external and internal links help search engines understand what your page is about and how the pages on your site are related to one another.
If you’re using the Simple Text block to add text to your app, you can easily add hyperlinks through the text editor.

_The link option in text editor_
If you’re using another block type that doesn’t have a link option for text, you can simply add an **HTML \ tag** inside the text. The following screenshot illustrates this on the example of a [Hero block](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/hero/avyLWEvNZNUqYewF51kMLA).

_Linking from a Hero block_
---
# Site SEO
Source: https://docs.softr.io/publishing/site-seo
Your Softr app’s SEO settings are available in the SEO section of your [App Settings](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/general-settings/7YdGy1J8X2tjJSv8BGvWQU), where you can verify your site with Google, customize the robots.txt file, and apply URL redirects.
---
# Page SEO
Source: https://docs.softr.io/publishing/page-seo
You can add a meta title and description in the SEO section of the page’s [settings](/0392ff65acfe4b1c96923c1aac7982f7). The meta title should be around 40 characters or less and the description should be anywhere between 160-180 characters. To open the page settings, click on the little gear icon in the upper left of an page in Softr Studio:

Once open, click on the SEO dropdown section to access the title, description and other settings.
1. **Title** - This normally appears in the tab of the browser and in search engine results if Search Indexing is enabled (see below). Should be around 40 characters or less
2. **Description** - Appears in search engine results if Search Indexing is enabled. Should be between 160-180 characters.
3. **Search Engine Indexing** - This toggle will allow search engines to find and index the page. If turned off, the page will not be visible to search engines.
4. **Canonical URL** - The canonical URL is the preferred URL for this page. If set, you can have similar pages indexed under an existing page to avoid conflicts in search results.

For any additional configs such as applying [structured data](https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data), etc. use the Custom Code (header or footer) area in the page’s settings.
---
# Item Details SEO
Source: https://docs.softr.io/publishing/item-details-seo
To display the details of a [List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU) item, we use the [Item Details](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/item-details-block-/4bE8XaFbJp45wkAwuWiz8f) block, which generates and displays the data for each list entry **on the same page**. To index each item’s details as a separate page that can be discovered by search engines as well as apply a custom slug and [meta data](https://developers.google.com/search/docs/crawling-indexing/special-tags), you can set up SEO parameters for your Item Details data.
## How to set up item detail seo
Since there's only one Item Details page for a specific List, you can define custom SEO parameters for each List item page within your data source.
> **Tip**
>
> The SEO parameters will be applied only if the Item Details page is valid, i.e. it is linked to a specific List block.
The following fields can be added (**please, take into account that the names are not case-sensitive**):
- **SEO:Index** – indicates whether the item page should be indexed or not. Can take yes/no, 1/0, true/false values. If positive, the page will be indexed by search engines and added to Sitemap.
- **SEO:Slug** – Here you can define a custom URL [slug](https://en.wikipedia.org/wiki/Clean_URL#Slug) for the item page. If left empty, the automatically-generated slug will be used for the item page. Your final shareable URL with the SEO slug attached will look like this: `https://yourdomain.com/page-name/SEO-slug/r/recordID`. Do not store a `/` in the database; Softr will append this for you.
- **SEO:Title** – Custom meta title for the page.
- **SEO:Description** – Custom meta description for the page.
In the example below, you can see how the SEO fields filled in for a "Leather Shoes" product.
> **Tip**
>
> The data source configuration described here is all you need to do. **Nothing needs to be done in your Softr application in order to enable the SEO setup.**

_SEO fields example_
> **Tip**
>
> If you have too many (**more than 1000**) entries that you want to index, the system can have issues adding them to the sitemap automatically. To address this, add **/generate-sitemap** at the end of your site URL (e.g. yourdomain.com/generate-sitemap) in the browser address bar and hit enter. After the action is complete, all your List Details URLs should be added to your sitemap.
## Social media
Similar to SEO fields, you can also add the following social media parameters to specify how each list item page should appear when shared on social media:
- **Social:Image**
- **Social:Title**
- **Social:Description**
You can check out how the page social parameters work [here](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/page-settings/49UoDpTpTPJe69RafDsALq). The names are not case-sensitive. Below is an example of the social fields added for a particular list item.

_Social fields example_
There are tools for [Twitter](https://cards-dev.twitter.com/validator) and [LinkedIn](https://www.linkedin.com/post-inspector/) that can be used to check how the page's social tags will appear on those social networks.
---
# Footer Settings
Source: https://docs.softr.io/application-settings/footer-settings
Footers allow your app users to access links and pages at the bottom of your app pages. Sometimes you may have more links and screens to show them than can fit on the main navigation. Footers are a great way to provide complementary and enriches information about your app that are not as commonly needed, such as Terms of Service, Privacy Policy links, Careers pages, social links, etc.
> **Info**
>
> Any Footers you create can be enabled or disabled on any page in your app. For instance, you may want a footer on your landing page, but not on the dashboard page once your users are logged in.
## Creating Footers
You can create and edit footers in Softr by following these steps:
1. **Click on the Pages menu and open the page’s settings**
Click on the Page menu to open all the pages in your app, then click on the gear icon to open the settings for the desired page.

2. **Select the Footer section**
Click on the Footer accordion section in the page settings to expose another dropdown. Here you can choose “None” to show no footer on this page, select an existing footer, or create a new one.

3. **Create a footer**
Click **+ Create a Footer** and select it to enable it on the current page. You can manage and edit Footers by clicking the Manage Footers icon just below the dropdown. Here you can delete footers and see how many pages they are currently being used on.


4. **Edit the footer**
The footer provides a host of options so you can build exactly what you need. Once a footer has been turned on for a page, click anywhere in the Footer to open its settings panel. Let’s take a look at some of the options available.
**Rename**
You can rename the footer in the Content tab. This will also be reflected in the page settings options when selecting footers.

**Layout**
In the Layout section, you can choose the general format of your footer such as Columns or Simple. You can further refine this layout in other settings below. Also in this section is a toggle for centering the secondary Link section if using Columns, or centering all the content if using the Simple layout.

**Logo**
Here you can change which version of your logo you want to display in the footer, either horizontal or square. You can set the logo for your app in the [General Settings](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/general-settings/7YdGy1J8X2tjJSv8BGvWQU) of your app.

**Links**
In the Links section, you can add links to pages, external URLs, and create categories of links if using the Columns Layout. Whether or not you see a Secondary section will depend on the Layout you’ve chosen. To add a Category, click on the **Add Category** button. To add a link, select a category and click the **plus button** on the right side of the category. You can delete and rename links and categories by selecting them
For Simple layout and the secondary section on Column layout, you can add just links by clicking **Add Link**.

**Social Links**
Softr also makes is super easy to add social links to your footer. First, select whether you want monochrome coloring or colored icons. Then click on **+ Add** to add a new Social Link. Select a link to edit it’s icon and the URL it should link to. You can even upload your own icons if you like. To delete a social link, just hover over it and click the Trash can icon. You can reorder social links by clicking and dragging it up and down the stack of social links.

**Messages**
In the messages section, you can customize some text to be shown in the footer such as a tagline or copyright information. These can be turned on/off with the toggle and you can also use a handy placeholder `{{YEAR}}` to always display the current year in either field.

**Styles**
Click on the Styles tab to adjust the colors to be used in the footer. These are derived from the [Theme](/styling/7qXYEkNvWQamR6vcLXzZnF/application-theme/91YGSL2aDJajXdbPBhitbc) panel of your app.
Adjusting the sizing affects font size, logo size, margins, and other aspects of the footer.
If you need more customization you can always use [custom code](/custom-code/3idxDhKqz1qPdqBuWbs61G) as well.

## Adjusting the visibility of footer links
You can adjust which links and link categories are visible to different users based on their [User Group](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/user-groups/6XQfKMeKHUvBcAjKvLs3g3). To do this, click on the Content tab, hover over a footer link or link category and select the branching icon.

Here you can adjust which users the link or category is visible to as well as which devices the link should be shown on. For example, Logged-in users may not need to see a link to Sign up or login since they are already logged in.

---
# Page Settings
Source: https://docs.softr.io/application-settings/page-settings
Just like an app has various screens and views, your Softr app has pages that will be used to hold the content of your app. These pages are categorized into two different types:
- Application Pages - These pages will hold the primary content of your app, whether its static content or dynamic content pulled from your datasource. You can fully customize these to suit your needs.
- Utility Pages - These pages are generated for you and handle more of the “housekeeping” side of your app such as password reset pages, 401 pages, invalid link pages, signup, login, and more. You can customize these to match your brand, but the core function of these pages is set for you.
Pages work in tandem with Navigation to help create a fluid, seamless experience for both you as the builder and the users of your application. Learn more about [Navigation](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/navigation-settings/49UoDpTpTMxcBVDnRVTncV) here.
## Creating a page
You can access all pages by clicking on the [Pages](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/page-settings/49UoDpTpTPJe69RafDsALq) menu in the upper left of Softr Studio:

At the top of the Pages menu, you can see all of your app pages and also add new ones using the gold “**+”** button. You can re-order pages by clicking and holding on the Page name, then dragging it up and down the Page stack.

Hovering over any page will reveal a gear icon and an kebab icon. The kebab icon allows you to duplicate a page, delete a page, or hide a page by making it a draft. The only page that you cannot set as a draft or delete is the Home page. You can name change the Home page’s settings and duplicate it, but it cannot be hidden or removed (your app has to have a home page!).

Clicking the gear icon will let you edit the page’s general settings like name, url slug, SEO settings, Navigation, visibility, and more.

## Page Settings
**General**
In the general settings, you can change the Page’s name (visible in Studio and in search engine results) and the url slug for the page (used to link people directly to this page in your app).

**Navigation**
In this section, select the Navigation you want to use for this page. You can use different navigation for different pages, create a new navigation from scratch, or choose not to use navigation at all.

**SEO**
The SEO section is where you will define the parameters for optimizing the page for search engines so that when someone searches for your app online, it appears in the search results. You want to use the SEO section to plug in keywords and phrases that match what your primary audience is searching for. Alternatively you can turn off search engine indexing if you don’t want people to be able to find this page in online search results.
- **Title** - Shown in search engine results
- **Description** - Show in search engine results
- **Search engine indexing** - Turn this on for your page to appear in search engines and off to prevent search engines from showing it in search results. This is handy for hiding non-relevant pages to search engines such as account pages, private pages, or pages with sensitive information.
- **Canonical URL** - You can tell search engines to prefer another version of this page over the current one. For instance, you have an old pricing page called `/old-pricing` that you still need to reference and show up in search results, but you prefer to show the new one called `/pricing` anytime someone performs a search for “app pricing”.

Here is an example of a search result where the pages SEO settings are displayed in a search engine. You can see the title of each page, along with a description, nested under the home page (softr.io). Proper SEO settings will help search engines better understand your site, rank it higher in search, and provide enhanced search results like this:

**Social**
Here you can edit settings for the page when someone shares the page link on social sites. This information appears in the social preview. It can also be helpful in boosting SEO slightly.
- Title - This title is displayed as the page name in the social preview
- Description - This is displayed as the page description in the social preview
- Social Image - This image is shown in the social preview and looks best when following the recommended aspect ratio and pixel sizes.

Here’s an example of a social preview in iMessage on iOS. Note that the social preview will look a bit different for every platform:

**Default footer**
Here you can toggle whether to use the default footer you setup on the Home page or turn off the default and create a new footer specifically for the current page. You can also simply turn it off and not put in a footer if the page doesn’t need one. No footer is common for dashboards and reporting interfaces.

**Visibility**
Here you can select who this page should be visible to. Choose between All Users, Non-logged-in users, all logged-in users, or logged-in users from a specific user group(s). If a user tries to visit a page they are not allowed to see, they will be redirected to the Permission Denied utility page (401 page). More on utlity pages below. For more information on page visibility, you can also check out [this help article](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/page-visibility/nWJaN689VKA1TUeaEfzK9u).

**Custom Code**
In the custom code section of the page settings, you can inject HTML, CSS, and vanilla Javascript into the header or footer of the page. Any code added in these sections will apply only to the current page. You can learn more about implementing custom code and see some code snippets in our [Custom Code docs](/custom-code/3idxDhKqz1qPdqBuWbs61G).

---
# Utility Pages
Source: https://docs.softr.io/application-settings/utility-pages
Utility pages are setup for you automatically, based on the functionality you setup in the [**Authentication**](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/user-authentication/7gJmq6B7syYE3hRoFxLs5J) tab of the Users menu. They cannot be deleted, but you can disable certain ones depending on your User Authentication settings. They facilitate core functions of any web app so your users have a great experience and you don’t have to spend time figuring out what to build or how to build it.

While you can change the name and url of these pages in the page settings, we recommend sticking with the defaults. You can also edit the branding of these pages. Each utility page will have its own settings and capabilities. Let’s explore the functions of these pages as they are know by their default names:
- **Log in** - This page is to let your app users log in to your app. You can also create multiple login pages, which is helpful for onboarding different roles or branding them in different ways. It is only available in your app if Login is enabled in your User Authentication settings.
- [**Sign up**](https://docs.softr.io/building-blocks/vikC2AWEpQGkZd4jGyoVxo/signup/54HYs3JEjYZA33S96fP3de) - This page is to allow people to sign up to your app as a user. You can also create multiple signup pages, which is helpful for onboarding different roles or branding them in different ways.It is only available in your app if Signup is enabled in your User Authentication settings.
- [Onboarding Flow](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/onboarding-flow/5MmuwRtpDR2JL56SooLXgo) - The onboarding flow pages allow you to build custom user onboarding steps or flows that new users can go into based on things like their user group, email domain, etc. You can setup flows to route people to different pages, ask them to complete their profile, or even create their company page before getting deeper into the app.
- [**Account settings**](https://docs.softr.io/building-blocks/vikC2AWEpQGkZd4jGyoVxo/account-settings/54HYs3JEjZj8DGwRCNUpH9) - This page is to allow users to edit their account/profile information such as their name, email, password, avatar, and any other information you want to let them edit. It is only available in your app if Login is enabled in your User Authentication settings.
- **Forgot password** - This page is to allow users to enter the email for their account so they can receive a forgot password email. It is only available in your app if Login is enabled in your User Authentication settings.
- **Reset password** - This page is to allow users to enter a new password after clicking on the Reset password link in the [forgot password email](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/user-email-notifications/sZRpewgUkBFFvhKSsQrBx7#forgot-password-email). Its only available in your app if Login is enabled in your User Authentication settings.
- **Link expired** - This is shown to people who are using a valid link but whose login session has ended or the list item is no longer available. It will always be available in your app and cannot be deleted.
- **Permission denied** - This is equivalent to a traditional 401 page and is shown to users who try to access pages they are not allowed to see. It will always be available in your app and cannot be deleted.
- **Page not found** - This is equivalent to a traditional 404 page and is shown to users who try to access a page or link that does not exist in your app. It will always be available in your app and cannot be deleted.
---
# Navigation settings
Source: https://docs.softr.io/application-settings/navigation-settings
Navigation is how your Softr app users move around in your app and it describes menus that you can setup to accomplish this. You can customize your users’ experience by defining which navigation they see, which buttons they see, what those buttons do, and even show tablet and mobile-friendly navigation layouts.
> **Info**
>
> Much of what your app Navigation does and shows depends upon your [User Authentication](/core-concepts-overview/c5VwEbsWtTfPyUZjmEKvfx/user-authentication/7gJmq6B7syYE3hRoFxLs5J) settings and the [Pages](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/page-settings/49UoDpTpTPJe69RafDsALq) available in your app. We recommend reading up on those before exploring this article.
When you create a Softr app, you’ll be given a default Navigation bar. This default navigation cannot be deleted, but it can be turned off or modified to suit your needs. You can also create multiple Navigations and choose which pages each navigation should be on.
## Setting up page navigation
To turn on Navigation for a page, go to the page settings and select the Navigation dropdown. Here you can choose to either turn off the navigation for the page, select an existing navigation, or create a brand new navigation. Any new navigations you create can also be used on other pages.

Selecting the navigation block will open up its settings where you can edit all of its settings. These settings will be applied to any page this Navigation is on.
### Content
With the navigation block selected, you will be able to change the Navigation’s name and see the Content tab where you can adjust various settings for your navigation.

**Layout**
Clicking the layout pane will allow you to set the Navigation to either side nav, top nav, or both. You can also adjust the navigation layout for both Desktop or Mobile/Tablet by clicking on the corresponding icon.

**Logo**
Choose to show either the banner (horizontal) version of your logo or the icon (square) version of your logo. You can set the logo in your app’s General settings.

**Links**
The Links section allows you to provide clickable text for your users to navigate around pages in your app or link out to external websites. You can organize links into the primary or secondary sections and even place links inside categories for better menu structure. To add a new link or category of links, simply click the **+ Add** button in either the primary or secondary sections. To reorder pages in the stack, simply click and drag on the page name.

On any link you add, you can set the name, icon and an optional subtitle . Depending on the type (page, external URL, or category), you can also define other parameters as well like the link location and where it should be opened. When choosing **Open page** as the action, all of your existing pages will be available to choose from.

You can also adjust the links on Desktop and Mobile/Tablet separately (1), toggle on the heirarchy lines within categories (2), and control which links are visible to certain user groups (3).

**Buttons**
Buttons work much the same as links, but are visually shown with a background instead of just clickable text. You can adjust button visibility for Desktop or Mobile/Tablet as well as the visibility of buttons for specific user groups. In contrast to links, Buttons do not have the option for categories.

**User Menu**
If this is turned on, your users will be able to navigate to their Account Settings page and Sign Out of their account. These two options are required and cannot be deleted if User Menu is turned on. You can also add additional links and pages to this menu though if needed. We recommend always turning on User Menu if you have Login enabled for your app.

### Styles
In addition to the Content Tab, clicking on the Styles tab at the top of the Navigation settings will bring up some options for customizing the look and feel of your Navigation. You can adjust the styling separately for Desktop and Mobile/Tablet.

The Styling select dropdown will show 3 main options, all of which are derived and adjusted automatically based on the settings in the [Theme menu](/styling/7qXYEkNvWQamR6vcLXzZnF/application-theme/91YGSL2aDJajXdbPBhitbc):
- Regular - This will adjust the navigation styling to match the background colors in the Theme menu.
- Accent - This will adjust the navigation styling to match the accent colors in the Theme menu
- Soft Accent - This will adjust the navigation styling to be a lightened shade of the accent color in the Theme menu.
You can also adjust the overall size of the navigation. This affects font size, button size, icon size and margins. In addition to size, you can change the rounding of the buttons.
---
# Page and Block Embed
Source: https://docs.softr.io/application-settings/page-and-block-embed
> **Note**
>
> Page and block embed is available for users on the [Basic plan and above](https://www.softr.io/pricing).
Softr allows you to embed any block or page on third-party site. Let’s see how that works.
## Block embed
The **Block Embed** option is located at the bottom of the **Features** tab in [block settings](/ccb7c7ca297742f782274da8b36c3bb2). Using this feature, you can embed the block on another website. Just copy the block code snippet and paste it wherever needed.

Getting the block embed code
## Page embed
You can embed any Softr page on an external website using the following code:
```javascript
```
Adjust the code:
1. Replace **example.softr.app** under **src** with your app's Softr subdomain or your custom domain if you've connected one. Add the page path you would like to embed e.g. `my_softr_domain.com/page1`. If you want to embed the Home page, no page path is needed.
2. Inside the value of **id** ("`softr-we-erw45hrubuyt23`" in the above code), replace the part that comes after `softr-` with the actual ID of your page, which is the last component of the page's URL when it's open in the Softr Studio (see below).

_Locating the page ID_
---
# Block Actions
Source: https://docs.softr.io/application-settings/block-actions
There are several actions that can be performed on a block to delete it, copy to another page or application, and so on. The actions toolbar appears when you hover over the block in Studio. So, let's quickly go over each one.
## Delete

_Delete action_
Use this to delete the block. Note that this action can't be undone, so make sure you really don't need the block anymore. If you might need it in the future, you can use the **Hide** action, which we'll consider further.
## Move up or down

_Move actions_
Using these actions, you can move the block up or down on the page.
## Duplicate

_Duplicate action_
This action creates an exact duplicate of the current block below it.
## Copy to

_“Copy to” action_
This option allows you to copy the block to any of your Softr apps. Choose the app you want to copy the block to and select the page in the corresponding dropdown.
> **Tip**
>
> Please, note that if you copy the block to another application, any visibility or edit permissions that are configured for the block will be reset.
>
> For blocks connected to Airtable (e.g. Lists, Forms), the configs (Airtable base/table connection, field mappings, conditional filters, etc.) will be preserved if the new application is connected to the same Airtable account. Otherwise, those will be reset as well.
## Notes

_Block notes_
Using this feature, you can add notes to a block. This can be used to store some important information about the block to be retrieved in the future or, for instance, to comment on blocks and exchange ideas when working on an application together with [collaborators](/workspace-and-billing/jZP6yaeXMiJCuB6HhS4xKd/workspaces-and-applications/kTbEWSYXhBCbtTB4K9dpKs).
You or your collaborators can add as many notes as needed, which will be stored as a thread (latest notes first) and will be accessible at any time in the future.

_Adding notes to a block_
The author of the note can also edit or delete it.

_Editing/deleting a note_
## Hide visibiity

_Hide visibility aciton_
Use this option if you want to hide the block temporarily. It will stay on your page but will become blurred and won't be visible to your users.
---
# Block Version Update
Source: https://docs.softr.io/application-settings/block-version-update
## Adding a new block version
If a new version of a particular block has been released, you'll see an **Block Update Available** notification at the bottom of your block settings sidebar (as shown below). Using this functionality, you can update your block to its latest version with a single click, preserving all the stylings and configurations.

_Block update notification_
Click **View details** to see the update changelog and make the update.

_Update pop-up with changelog_
> **Tip**
>
> Note that there might be cases (of which you'll be notified in block settings) when the **Update Block** option won't be available and you'll need to remove the block and add it again, redoing the block setup.

_Manual block update notification_
## Deprecated block versions
Occasionally, we release updated versions of specific blocks and mark older ones as deprecated. A deprecated block will still work in your published app, but its settings can’t be changed.
If you see a deprecated message in the block’s settings, we recommend adding the latest version to benefit from new features, improvements, and ongoing support.
---
# General Settings
Source: https://docs.softr.io/application-settings/general-settings
Before starting to build your site, you might want to check the application **Settings** to apply some general configurations. The settings can be accessed from the left-side toolbar as shown in the following screenshot.

_Application settings_
So, let’s go through the sections one by one.
## General

_General settings_
When you create your application a random name and subdomain are automatically assigned to it, which can be customized in this section. The **Application Name** is for your own reference and will not appear anywhere after publishing the app. Next, you can customize your subdomain as follows: **https\://\.softr.io**. You can also use a [custom domain.](/publishing/9qTmU2Lj8Gnpr1Ue6dEAkX/add-a-custom-domain-to-your-app/93K5bLJN3n91MRo9uRGdAf)
Next, you have the option of adding a **favicon**. Please, follow the provided size and format recommendations. There are numerous services (e.g. ), that you can use to generate a favicon of the required format and size.
Lastly, you have the **Softr branding** toggle, which allows you to enable/disable the "Made with Softr" badge on your site.
> **Note**
>
> Disabling Softr badge is available for users on the [Professional plan and above](https://www.softr.io/pricing).

_Softr branding_
## Custom Domain
[General Settings](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/general-settings/7YdGy1J8X2tjJSv8BGvWQU)
Here you can use your own custom domain to run your website or web-application on. More detailed info on configuring a custom domain can be found [here](/publishing/9qTmU2Lj8Gnpr1Ue6dEAkX/add-a-custom-domain-to-your-app/93K5bLJN3n91MRo9uRGdAf).
## Integrations
In this section you have the list of all the available integrations that can be connected to your app. Check out the **Integrations** section of this library to find more info on each option.
## SEO
Here you can configure general SEO settings, while SEO details for individual pages can be set in **page settings**.
### **Google Site Verification**
In the **Google Site Verification** field you need to add your ID to verify your ownership of the website and link it to Google Search Console.
To get the ID, on your Google Search Console dashboard, go to **Settings => Ownership Verification,** choose the **HTML tag** option, and copy the value of **content** as shown below.

_Getting the verification tag_
Lastly, you need to paste the code inside corresponding field, and hit **Save**. Don't forget to **publish** your Softr app afterwards.

_Pasting the verification ID_
### **robots.txt**
Further on, you can fill in the **robots.txt** file to provide some instructions for web crawler. You can find more info on **robots.txt** [here](/publishing/9qTmU2Lj8Gnpr1Ue6dEAkX/add-a-custom-domain-to-your-app/93K5bLJN3n91MRo9uRGdAf).
### **URL redirects**
Using this option, you can apply 301 redirects within your Softr app. To add a new redirect rule or edit the existing ones, you need to click on the **Edit** button.

_Redirect edit button_
Next, you'll see a pop-up with the list of all the existing redirects. To add a new redirect rule, you need to define the page that needs to be redirected (**Old Path**) and the destination page (**New Path**).

_Adding a redirect rule_
**Wildcard redirects**
You can apply wildcard redirects using an asterisk in your path. Let's consider a few examples:
**/old-folder/\* => /new-destination** - This means that all the paths under "**/old-folder"** (such as "/old-folder/path1" or "/old-folder/path2") will be redirected to the same single destination.
## Custom Code
In this section, you can add custom code to your app header and footer. The first one will be applied before the **\** tag, and the second one will be applied before the **\
** element and is meant for adding scripts.
### **Custom Code use case**
Let's suppose we want to add a Facebook Messenger to our Softr app, so that users can contact our Facebook Page.
**Getting the Code**
In the Page Settings, we are going to navigate to **Messaging**, and select **Add Messenger to your website**, as shown below.

_Add Messenger to your website_
In the next page, we need to hit **Set Up** and configure the chat plugin.

_Set up the chat plugin_
In the pop-up that appears next, you need to set your chat language, add domain and get the chat widget code as shown below.

_Configuring the chat plugin_
When you're done with configuring the plugin, hit Publish in the bottom right corner of the screen and you're all set.

_Publish_
**Applying the Code**
Lastly, we'll go back to our Softr app's **Settings** and paste the chat plugin code into the footer area. Below you can see the process of adding the code and viewing the chat widget on the website.

_Adding the code and publishing the widget_
## User groups and permissions
Learn how to create and apply user groups to blocks/pages [here](/publishing/9qTmU2Lj8Gnpr1Ue6dEAkX/add-a-custom-domain-to-your-app/93K5bLJN3n91MRo9uRGdAf).
> **Tip**
>
> The greyed out Softr informational text cannot be changed or removed. This is to protect email recipients and legitimate Softr users. If you wish to send more customized emails, consider using automation software (Make, Zapier) and a transactional email service provider such as Mailersend, SendGrid, Mandrill, or Brevo.
## Date & Time
In this section you can set the default date and time settings for your app such as default Timezone and Date and Time formatting. Access it in the Settings panel.

You have two options to choose from:
- **Date and Time Format** - Here you can choose whether you want the date and time formatting to be the same for everyone or based on each Logged-in User’s local formatting preferences. Additionally, use the checkbox to Localize the day and month names to the local language.
- **Timezone** - Choose to either keep the timezone the same for everyone or localize it for each user. If you choose to use the same timezone for everyone, you’ll be asked to set the timezone.

## SAML Configuration
See how to configure SAML on your Softr app [here](/publishing/9qTmU2Lj8Gnpr1Ue6dEAkX/add-a-custom-domain-to-your-app/93K5bLJN3n91MRo9uRGdAf).
## OpenId Settings
You can find how to configure OpenId settings [here](/publishing/9qTmU2Lj8Gnpr1Ue6dEAkX/add-a-custom-domain-to-your-app/93K5bLJN3n91MRo9uRGdAf).
---
# App History
Source: https://docs.softr.io/application-settings/app-history
The App History section, which is located in your Softr App settings, provides you with a timeline of the changes that have been made to your app throughout its existence. It allows you to save your current "state" whenever needed to be able to go back and resume from that state at any time in the future. Just like in a shooter game. So, whenever you feel that your app has taken a wrong turn or, say, you've deleted some info by mistake, you can just click on one of the previous app versions and start over.
The versions are available through **snapshots** that are taken either automatically or manually. Let's take a closer look to better understand how this works.
> **Tip**
>
> Please, note that the following changes will not be reflected in app history and **you won't be able to undo them:** Page name or path change; App name change; Domain or subdomain setup; Adding, editing, or deleting users.

_Autosaved and manual snapshots in the App History_
## **Saving a snapshot**
A snapshot is saved automatically as soon as you complete 10 actions inside your Softr app (e.g. add a new block, edit text in a block, save page settings). So, after every 10 actions, you'll have an autosaved snapshot stored in your app history. However, you can also manually create a snapshot at any point (see below).

_Manually creating a snapshot_
As you can see, when taking a snapshot manually, you can also assign a custom name to it and edit it later on.
## **Restoring from a snapshot**
Now let's see how you can restore a version of your Softr app from your snapshots. The process is pretty straightforward, and you just need to go to your App History, select one of the snapshots, and hit **Restore**.
> **Tip**
>
> Note that a new snapshot of your current app version will be created automatically right after you hit Restore to go to a different version.
Below, you can see how we restore a previous version of our app, and the Gallery block, which had been added later on, is no longer there.

_Restoring from a snapshot_
> **Tip**
>
> On Softr's free subscription plan, you'll have access to and can restore from the latest 5 snapshots only. However, on all the other (paid) plans, you can restore from any snapshot stored since the creation of your Softr app. Upgrading from a free plan will give you full access as well.
That's all you need to know to be able to navigate through your App History and transition between different versions. Enjoy!
---
# Advanced Settings
Source: https://docs.softr.io/application-settings/advanced-settings
In the Settings tab of your app, you also have the ability to change some optional, but advanced settings for your entire app. You can access these by clicking on the Settings tab on the left, then clicking on Advanced Settings at the very bottom of the list:

_Click on Settings tab, then Advanced Settings at the bottom of the list._
## User Caching
When enabled, user data caching improves the speed of your Softr apps by caching user data for 2 minutess to allow for faster list filtering and page loading where logged-in user data is required. We anticipate that updates to user records are less frequent than updates to other records so cache of 2 minutes allows your Softr app to serve up user data much faster. Otherwise, with User Cache off, Softr is forced to get the user’s record each time a page is loaded, regardless of whether any user data has changed. This makes your app slower for no beneficial reason.
If app speed is priority for you, then leave User Caching on. If data freshness is more important and you don’t mind waiting a while on each page load, then turn User Caching off. If you’re wondering which you should choose, we recommend turning User Caching ON for 95% of use cases.
## Allow Embedding
If this is enabled, anyone with the public link to your app can embed the app in another webpage or application. If your app is internal or contains proprietary functionality, it may be best to disable this feature. Try to avoid embedding webpages with multiple iFrames as this can create embeds within embeds. Some instances where this feature may be useful:
- Embed your app in the main landing page of your company website.
- Embed some Softr charts in your primary webpage.
- Embed a list of contacts or resources into a slide deck.
- Embed your SaaS product into a customer’s website.
---
# Dynamic App Logo
Source: https://docs.softr.io/dynamic-app-logo
By default your app shows one logo to everyone. With **Dynamic logo** you can instead pull the logo from a field in your data, so each logged-in user sees a logo that belongs to them such as their own company's branding in a client portal, or their department's mark in an internal tool. It's also useful for co-branded apps or tools!
You configure it in **Settings → General**, in the **Logo** section.

_The Logo section in Settings → General, with the Dynamic logo toggle at the bottom._
## Before you start
Dynamic logo reads images out of your data, so you need two things in place first.
1. **A default logo**
Upload a **Horizontal** and, if you use it, a **Square** logo in the Logo section. This is what users see when no image is found for them, so it is worth setting even when most users have their own. See [General Settings](/application-settings/general-settings) for the rest of this panel.
2. **A field holding each user's logo**
Add an image field to the table your logos live in and fill it in. In [Softr Databases](/softr-databases/field-types) this is a **File** field; in [Airtable](/data-sources/airtable) it is an attachment field. In other data sources it may be an attachment or file field of a similar nature.
> **Tip**
>
> Softr recommends logo images at least **400px** in height, in **SVG** or **PNG**. Keep the horizontal (banner) and square (icon) versions as separate fields — the app uses whichever shape a given surface calls for.
## Turn on Dynamic logo
1. **Open the setting**
In Studio, open **Settings** from the left toolbar, then **General**. Scroll to the **Logo** section.
2. **Switch on Dynamic logo**
Turn on the **Dynamic logo** toggle at the bottom of the section. A **Configure** button appears below it, marked with a dot to show it still needs setting up.

3. **Click Configure**
This opens the **Configure dynamic logo** dialog, where you point Softr at the fields holding your logos.

_Turning on Dynamic logo reveals the Configure button._
## Map your logo fields
The **Configure dynamic logo** dialog asks where the logos are stored. Work through it top to bottom — each choice narrows the next.

_The Configure dynamic logo dialog._
1. **Account**
Pick the data source holding your logos. Every data source connected to your workspace is listed, and **Add another data source** at the bottom lets you connect a new one without leaving the dialog.
2. **Database**
Choose the database or base within that account.
3. **Table**
Choose the table. This should be the table your app's users come from, so that Softr can match the logged-in user to a row.
4. **Horizontal logo field**
Choose the field storing the wide, banner-shaped logo. Image fields appear under **Suggested**; everything else is under **Other fields**. Use the search box if the table has many fields.
5. **Square logo field**
Choose the field storing the square, icon-shaped logo. You can leave this as **None** if you only use the horizontal logo.
6. **Save**
Click **Save** to close the dialog, then **Save** again at the bottom of the General settings panel. [Publish your app](/publishing/publishing-your-softr-app) for the change to reach your live users.
> **Note**
>
> Both field dropdowns include a **None** option, so you can map only one shape and let the other fall back to your default logo.
## What users see
Softr looks up the logged-in user's row and uses the image in the mapped field. The logo appears wherever your app logo normally does — the [navigation menu](/application-settings/navigation-settings), the login page, and the [footer](/application-settings/footer-settings).
**If no image is found for a user, they see the default app logo** you uploaded in the Logo section. That covers users whose logo field is empty, and users who have no matching row at all — so the app never renders without a logo.
> **Warning**
>
> The login page is shown _before_ anyone signs in, so there is no user to look up yet. Expect the default logo there, and treat the dynamic logo as something users see once they are inside the app. If you need branded log in or sign up pages, try creating separate Utility pages for those with unique URLs for each client or company.
## Choosing where to store the logos
Which table you point at depends on how your data is shaped.
**Logo on the user record**
The simplest setup, and the one to reach for first. Add the image field directly to your users table and fill it in per user. Point the dialog at that table and map the field. This works well when logos are genuinely per-person, or when your user list is short enough that repeating a company logo across a handful of rows costs nothing.
**One logo per client company**
In a client portal you usually store the logo once on a Companies table and link users to it. You don't need to duplicate that image onto every user — use a [Lookup](/softr-databases/related-record-lookup-and-rollup-fields) field to pull it through.
1. **Store the logo on the company**
Add a File field to your Companies table and upload each client's logo once there.
2. **Link users to their company**
Make sure each user record has a Related Record field linked to the right company.
3. **Add a Lookup field on the users table**
Create a **Lookup** field, set **Lookup source** to your linked record field, and set **Field to look up** to the company's logo field. The image now resolves on each user's row.
4. **Map the Lookup field**
In the Configure dynamic logo dialog, pick your users table and select the Lookup field as the horizontal or square logo.
Update a company's logo once and every user linked to it picks up the change — no per-user edits, and no workflow to keep copies in sync.
> **Warning**
>
> Map the **Lookup** field, not the linked record field itself. A linked record field can be selected in the dropdown but holds no image, so users would fall back to the default logo.
> **Note**
>
> If a Lookup renders empty even though the company has a logo, check the company record itself rather than the Lookup. Re-linking the user to a freshly created company record is the quickest way to confirm the lookup is configured correctly.
## Keep the logo from disappearing
If your logos live in a Softr Databases **File** field, check the field's **Expiring file links** setting.
When that setting is on, Softr hands out links that stop working after a set period, customizable anywhere from 1 hour to 168 hours (7 days). That is useful for private documents, but a logo is meant to be public and permanent. Open the field, switch **Expiring file links** off, and your logo URLs will keep resolving.
It's also helpful to turn off the **multiple files** option here, since Softr will only use the first file in the field. Storing more than one can become confusing if the wrong one is being show in the app.

_The Expiring file links setting on a File field._
## Troubleshooting
**Everyone still sees the default logo**
Softr falls back to the default whenever it cannot find an image for the user. Check that the mapped field actually holds an image on that user's row, that you picked the table your users come from, and that you saved both the dialog and the General settings panel and then published.
**The logo shows in Studio but breaks later for users**
This is the signature of expiring file links. Turn that setting off on the File field holding your logos.
**Only some users get their own logo**
Those users' rows are missing an image, or they have no row in the mapped table. Users added manually rather than [synced from your data source](/add-and-manage-users/syncing-users-with-a-data-source) are a common cause, since they may not exist in the table you mapped. If you are using a Lookup field, check that the affected users are linked to a company at all, and that the company record has a logo. Users linked to the same company should all resolve identically. If one company's users are the only ones failing, the problem is that company record, not your configuration.
**The square logo never appears**
Some surfaces only use the horizontal version. Check which one the surface is set to show — [Navigation settings](/application-settings/navigation-settings) and [Footer settings](/application-settings/footer-settings) each let you pick between the banner and square versions of your logo.
## Related
[**General Settings**](/application-settings/general-settings)
The rest of the app settings panel, including favicon and Softr branding.
[**Navigation settings**](/application-settings/navigation-settings)
Choose which version of your logo the navigation bar shows.
[**Footer Settings**](/application-settings/footer-settings)
Choose which version of your logo the footer shows.
[**Application Theme**](/styling/application-theme)
Colors, fonts, and the rest of your app's branding.
---
# Custom Code Block Overview
Source: https://docs.softr.io/custom-code/custom-code-block-overview
> **Note**
>
> Custom code is available for users on the [Pro plan and above](https://www.softr.io/pricing).
The **Custom code** block is a powerful feature which allows you to insert custom snippet of code, including **HTML, CSS** and/or **Javascript**, anywhere in your application. The code snippet will be added inside the html element.
**NOTE:** If you want to add custom code snippets inside "\" element, or at the end of the page, before the "\" element closes, you can do that from [Settings => Custom Code](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/general-settings/7YdGy1J8X2tjJSv8BGvWQU) for application level changes or from [Page Settings](/0392ff65acfe4b1c96923c1aac7982f7) for page level modifications. This tutorial covers the cases when you want to add a code snippet anywhere inside the "\" element.
## Adding a Custom code block
Custom code is added through the Custom Code block in **Blocks => Static => Custom code**.
> **Tip**
>
> You need to be on a paid plan to be able to use the **Custom code** block.
## Adding the code inside the block
Next, you need to open the block settings and paste the code snippet you would like to add. It can contain standard **HTML elements**, elements containing custom CSS rules, and even tags containing JavaScript code.

_Custom Code block_
Now, you can **Preview** your Softr app to see the changes.
## Use Case - Embed Calendly in Softr app
Let's see how the Custom Code block works on a specific example. We'll use it to embed a [Calendly](https://calendly.com/) widget within our Softr app.
### **Getting the Embed Code**
In our Calendly account, we are going to navigate to **Share Your Link** in the **Account** dropdown menu.

_Share your link_
In the pop-up that appears next, let's choose the embed option as shown below.

_Selecting 'Add to Your Website'_
Next, we'll select **Inline** **Embed** and hit continue.

_Choosing 'Inline Embed'_
In the following screen, we can customize our Calendly widget, and, when we're done, we need to click **Copy Code**.

_Copying the Calendly page code_
### **Adding the code to the block**
Finally, we will go back to our Softr app, paste the code in the **Custom code** block, and hit **Preview** to see what it looks like.

_Applying the code_
## Guidelines for custom code in SPA mode
In SPA mode (Single-Page Application), custom code works a little differently than non SPA mode. Since we never do full page reload in the SPA mode, page level custom code needs to ensure that it doesn't interfere with other pages.
## TL;DR
- Keep page specific code out of app level custom code.
- Whenever possible, use plain HTML/CSS instead of Javascript.
- Use `
```
## Cleanup timers and resize observers on page unload
If your page custom code sets up timers or resize observers, they need to be cleaned up before the page unloads. This ensures that the timers don't keep running after navigating away from the page.
For example, here's a custom code block which shows the number of seconds this page has been open for
```html
The page has been open for 0 second(s)
```
## Don't use DOMContentLoaded in page level custom code
DOMContentLoaded will only fire once, on app load. Navigating between the pages will **not** re-run the event listener.
Instead, `window.SOFTR_PAGE.waitFor` provides a simple way to wait for an element to be on the page before continuing.
```html
```
---
# Custom Code Snippets
Source: https://docs.softr.io/custom-code/custom-code-snippets
The following code snippets are not simple copy/pastes. Many of them need to be tweaked for your specific app and block names.
> **Tip**
>
> Code snippets mentioned here should be added to the page Settings -> Custom Code -> Code Inside Header, unless stated otherwise.
## How to get back to the previous dynamic page (with List detail block) without losing the record id parameter in the URL
```plain
```
## How to hide the lines on the list and list detail blocks where the rows are empty on Airtable
```plain
```
## How to set Gradient colors for your entire page’s background.
```plain
```
## How to get a prefilled URL with record ID and redirect it to the detail page after login.
```javascript
```
## Hide the button if there is no link coming from Airtable. (href is empty)
```javascript
```
## Code for dividing the block with custom code block
```javascript
```
## Code for changing Charts colors
```javascript
```
## Making a video full width AUTOPLAY block
```javascript
```
## code that will allow to display always expended items from the "List with Columnar Sliding Cards Expanded" block.
```plain
```
## For block’s background image
```css
```
## Translate the "Yearly" and "Monthly" options in the pricing block
```plain
```
## Create breadcrumbs so that the users can navigate across the different sections of the application.
```javascript
```
## Hide chart data refresh message

```css
```
## Hide the labels on a sign-in or sign-up form
Replace `#user-accounts2` with the name of your block. Paste this code in the header of the sign-in/sign-up page.
```javascript
```
---
# Custom Code Events and Style Selectors
Source: https://docs.softr.io/custom-code/custom-code-events-and-style-selectors
> **Tip**
>
> Code snippets mentioned here should be added to the page Settings -> Custom Code -> Code Inside Header, unless stated otherwise.
## Global variables
- There is a `
` element on top of the document `` that stores application id and page id on it’s `data-appid` and `data-pageid` attributes.
- If there is a logged in user `window.logged_in_user` object is available with `softr_user_email` , `softr_user_full_name` properties. If you have synced your users table with a data source, you will also be able to access the other properties about the user as well.
- Block specific data is stored on `window` object with `hrid` as an identifier of that block. (ex. `window['table1']` in case hrid is table1).
The `window[hrid]` object differs based on block type.
- List, List details, Kanban, Chart, Organization chart, Calendar, Twitter and Map blocks have `baseId` and `tableName` properties.
- Form block has `airtableBaseUrl` property
- Map block has `google_map_api_key` property
- There is `openSwModal` global method that opens given url in modal.
Example: `openSwModal('https://softr.io/')`
## Charts
### Chart colors
To change chart default colors we should set
```javascript
window['chart1-colors'] = ['#FE8070', '#DD7E6B', '#EA9999', '#F4CCCC', '#24A37D', '#AEAEB5', '#E25B5B', '#FFF974', '#4BAEAE', '#E5E5EA', '#33E4EF', '#C9DAF2'];
```
where `chart1` is the block hrid.
### Chart invalidate
Invalidate the chart cache after 5 seconds:
```javascript
```
where `chart1` is the block hrid.
### Chart reload
Reload after 5 seconds:
```javascript
```
where `chart1` is the block hrid.
### Chart invalidate and reload
Invalidate the cache and reload the chart:
```javascript
```
Where `chart1` is the block hrid
### **Chart v5 change colors depending on value WIP**
```javascript
```
## Browser Events
Adding **event listeners** to **elements** that were rendered by **React** is tricky.
You may **add** an **event listener** but after **React re-renders** the **component** it might **loose** your **listener** because React can (in some cases) remove and re-create element that you added the listener on.
To handle this the `event listener` should be added on `parent element` that doesn’t re-render and `check` the element `selector` after `event trigger`.
Example:
```javascript
const handler = (e) => {
if (e.target.closest('#table1 .ag-row')) {
// handle click event on ag-row
}
};
document.body.addEventListener('click', handler);
```
This way you can handle `click` event on table rows with `table1` hrid.
## Generic Custom Events
There are custom events that Softr blocks trigger or listen to.
We also add **hrid** to the event name to identify the block the event refers to.
### **block-loaded**
`block-loaded` event is triggered when React mounts the block into DOM. It can be used instead of `DOMContentLoaded` event that is used in old custom codes.
ex.
```javascript
window.addEventListener('block-loaded-table1', () => {
console.log('Block loaded');
});
```
### **get-record**
`get-record` event is triggered on every single data response from softr data service. It is used on list-details blocks and it can be used as for getting the data and using it for other 3rd party calls or as a indicator that after some small interval time the block will be fully rendered.
ex.
```javascript
const onRecord = (e) => {
// we got new data under e.details
console.log(e.detail);
//console.log {id: '***', fields: {...}}
};
window.addEventListener('get-record-list-details1', onRecord);
```
```javascript
const onRecord = (e) => {
setTimeout(() => {
// The block finish rendering
// I may do some staff here.
}, 50);
};
window.addEventListener('get-record-list-details1', onRecord);
```
```javascript
window.addEventListener('get-record-list-details1', (e) => {
// hide list details block if no record found
if (!e.detail.id) {
document.getElementById('list-details1').classList.add('d-none');
}
});
```
### **get-records**
`get-records` event is triggered on every data response from softr data service. It can be used as for getting the data and using it for other 3rd party calls or as a indicator that after some small interval time the block will be fully rendered.
ex.
```javascript
const onRecords = (e) => {
// we got new data under e.details
console.log(e.detail);
//console.log [{id: '***', fields: {...}}]
};
window.addEventListener('get-records-table1', onRecords);
```
```javascript
const onRecords = (e) => {
setTimeout(() => {
// The block finish rendering
// I may do some staff here.
}, 50);
};
window.addEventListener('get-records-table1', onRecords);
```
Also there is an `get-records:before` event that is triggered before sending request, It can be used to catch the inline filter or search field changes.
```javascript
const onFilterChange = (e) => {
console.log(e.detail);
//console.log { search: '', filter: [ { field: 'size', value: 'M' } ] }
};
window.addEventListener('get-records-table1:before', onFilterChange);
```
### **update-records**
`update-records` event is listened by all blocks that use external data.
It can be used to change/add/remove the data that should be rendered. Mostly it can be used in pair with `get-records`.
ex.
```javascript
const onRecords = (e) => {
const modifiedRecords = e.detail.map(({fields, ...other}) => ({
...other,
fields: {
...fields,
phone: fields.phone ? fields.phone.replace('+374', '0') : '',
}
}));
const modify = new CustomEvent('update-records-table1', { detail: modifiedRecords });
setTimeout(() => window.dispatchEvent(modify), 1);
};
window.addEventListener('get-records-table1', onRecords);
```
## Action Buttons
### **add-record**
`add-record-hrid` event is fired when the form submission in the add-record modal is triggered.
`add-record-success-hrid` event is fired when the submission is successful
`add-record-failure-hrid` event is fired when the submission has failed
```
```
### update-record
`update-record-success` event with field values is triggered after getting response with success status code.
`update-record-failure` event is triggered after getting response with error code.
ex.
```javascript
window.addEventListener('update-record-failure-list1', (e) => {
console.log('update record failure', e.detail);
// update record failure 'Email field is required.'
});
// To reload the page after record update on #list1 block
window.addEventListener('update-record-success-list1', () => {
window.location.reload()
});
```
### upvote-record
`upvote-record-success` event with field values is triggered after getting response with success status code and datail.
`upvote-record-failure` event is triggered after getting response with error code.
ex.
```javascript
```
### call-api (webhook-trigger)
`call-api-success` event with field values is triggered after getting response with a success status code.
`call-api-failure` event is triggered after getting response with error code.
ex.
```javascript
```
## Blocks Custom events
### Calendar block trigger reload block
ex.
```javascript
```
### List blocks trigger reload block
ex.
```javascript
```
## Form Custom Events
### **update-fields**
`update-fields` event is listened by blocks that use form inputs with Formik library. Currently it’s blocks under Form and User Accounts categories. It can be used to update input values with custom code. This is used to update form values from a code automatically… let’s say after form is rendered client side custom code fetches a data from third party API and wants to set into form to be submitted… (keep in mind user attributes and URL attributes can be prefilled with default functionality without code)
ex.
```javascript
```
### **submit-form, submit-form-success, submit-form-failure**
`submit-form` event with field values as an attribute is triggered before sending form submission request.
`submit-form-success` event with field values is triggered after getting response with success status code.
`submit-form-failure` event is triggered after getting response with error code.
ex.
```javascript
window.addEventListener('submit-form-form1', (e) => {
// e.detail is an object with form field names and values
console.log('form submit', e.detail);
// form submit { "Full Name": "Softr", "Email": "info@softr.io" }
});
window.addEventListener('submit-form-success-form1', (e) => {
// e.detail is an object with form field names and values
console.log('form submit success', e.detail);
// form submit success {
// payload: { "Full Name": "Softr" ... },
// response: { headers: {...}, data: {...}, status: 200 }
// }
});
window.addEventListener('submit-form-failure-form1', (e) => {
console.log('form submit failure', e.detail);
// form submit failure 'Email field is required.'
});
```
### **Customize form’s validation messages**
Make error massages of inputs in forms and user account blocks changeable/translatable via a custom code:
```
```
## Header Custom Events
### set-logo-link
`set-logo-link` event is used to set header logo link to custom url.
ex.
```javascript
window.addEventListener('block-loaded-header1', () => {
const detail = { link: 'https://google.com' };
window.dispatchEvent(new CustomEvent('set-logo-link-header1', { detail }));
});
```
### trigger action before logout
first will trigger custom action and after 300 ms will continue to Sign Out
ex.
```javascript
window.addEventListener('user-sign-out', (e) => {
// do some actions before logout - (300 ms)
});
```
### Sign-out user by clicking on custom button
`block-loaded` event is triggered when React mounts the block into DOM.
ex.
```javascript
```
## Tab Container Custom Events
`tab-selected` event is triggered every time the user selects a new tab in the Tab Container.
The event is triggered only when the active tab is changed, if the user clicks on the already active tab the event won’t be triggered.
ex.
```javascript
// Add an event listener for "tab-selected" event for Tab container with "tab-container1" id
window.addEventListener('tab-selected-tab-container1', (e) => {
// the selected tab id is stored in e.details
console.log(e.detail);
});
```
## Styling
There is still bootstrap included in the page, but it will be removed in the near future. So try not to use it.
Material-ui React component library is used in the new blocks. It adds classes to all small to large components with the prefix of `Mui` those classes can be used to add custom styles to the elements, but we may also change it to `Softr` or something similar in the near future (ex. `MuiInputBase` to `SoftrInputBase`).
Try wrapping selector with hrid to add more priority to your selector.
ex.
```css
#table1 .MuiInputBase-input {
border-left: none;
}
```
There are also some attributes that expose the content of the element. It can help identify and style them based on it.
- data-content attribute on tag elements
- data-rating attribute on rating elements
Because CSS supports attribute selectors, they can be used to style the elements based on content.
ex.
```css
// tags with content "Low"
#table1 .tag-item[data-content="Low"] {
background-color: #F00 !important;
}
// add span to the selector if you want to customize text color
#table1 .tag-item[data-content="Low"] span {
color: #FFF !important;
}
// tags that start with word "Low"
#table1 .tag-item[data-content^="Low"] {
background-color: #F00 !important;
}
// tags that have substring "low"
#table1 .tag-item[data-content*="low"] {
background-color: #F00 !important;
}
// ratings that are 1 start
#table1 [data-rating="1"] span {
color: #F00 !important;
}
```
### Overriding navigation styles
```css
```
### Kanban block custom column background colors
ex.
```javascript
```
### Styles and actions for Action buttons by custom code
ex.
```javascript
// ✅ get an element with data-action-button-id
const el1 = document.querySelector('[data-action-button-id="list1-visible-btn-0-rec1yIahkX1mZhLQn"]');
// ✅ get an element where data-action-button-id starts with list1-visible-btn or list1-btn
const el1 = document.querySelector('[data-action-button-id^="list1-visible-btn-"]');
// ✅ get all elements where data-action-button-id starts with list1-visible-btn
const elements = document.querySelectorAll('[data-action-button-id^="list1-visible-btn-"]');
#list2 button[data-action-button-id^="list2-visible-btn-_l26zaezue"] {
margin-left: 50px
}
```
```css
// ✅ style for all buttons where data-action-button-id starts with list1-visible-btn-
#list1 button[data-action-button-id^="list1-visible-btn-"] {
margin-left: 50px
}
// ✅ style for one of buttons with data-action-button-id-BUTTONID
#list1 button[data-action-button-id^="list1-visible-btn-_l26zaezue"] {
margin-left: 50px
}
```
### Selectors available for styling using custom code
Various CSS classes and `data-` attributes let you style UI elements and select them with JavaScript.
Class names use the `.softr-` prefix to distinguish them from internal classes that may change.
Similarly, stable `data-*` attributes use the `data-softr-*` prefix, with a few exceptions like `data-action-id`.
```css
/**
* Grid block's card container. Can be used to adjust the gap
* between the cards using the `gap` property
*/
#list1 .softr-grid-container {
gap: 24px;
}
/**
* Similar to `softr-grid-container` but for the list block
*/
#list1 .softr-list-container {}
/**
* Container for all fields in the list and list details blocks
*/
#list1 .softr-fields-container {}
/* Field labels for list and list details blocks */
#list1 .softr-field-label {}
/* The wrapping element for each field/modal field input has this attribute */
#list1 [data-softr-field-id='your-field-id'] {
/* Selects the wrapper div for the field with id 'your-field-id'.
You can find the field id from the browser dev tools.
*/
}
/* Various dialog containers */
#list1 [data-softr-dialog-type] {
/* Selects all dialogs in the list1 block */
}
#list1 [data-softr-dialog-type='UPDATE_RECORD'] {
/* Selects only the `Update record` dialog in list1 block */
}
```
### Worked out example for styling form inputs
Let's see how to customize the appearance of input fields in the "Add record" form.
Here's the end result:
```css
```
---
# SPA Custom Code Guidelines
Source: https://docs.softr.io/custom-code/spa-custom-code-guidelines
In the SPA mode, custom code works a little differently than non SPA mode. Since we never do full page reload in the SPA mode, page level custom code needs to ensure that it doesn’t interfere with other pages.
## TL;DR
- Keep page specific code out of app level custom code.
- Whenever possible, use plain HTML/CSS instead of Javascript.
- Use `
```
## Cleanup timers and resize observers on page unload
If your page custom code sets up timers or resize observers, they need to be cleaned up before the page unloads. This ensures that the timers don’t keep running after navigating away from the page.
For example, here’s a custom code block which shows the number of seconds this page has been open for
```text
The page has been open for 0 second(s)
```
## Don’t use DOMContentLoaded in page level custom code
DOMContentLoaded will only fire once, on app load. Navigating between the pages will **not** re-run the event listener.
Instead, `window.SOFTR_PAGE.waitFor` provides a simple way to wait for an element to be on the page before continuing.
```text
```
---
# Open AI
Source: https://docs.softr.io/integrations/open-ai
Now you can generate images and copy with the help of [Open AI](https://openai.com/) to really speed up the app creation process. Moreover, you can create apps that offer AI functionality to your users (like [copy.ai](http://copy.ai/) or [jasper.ai](http://jasper.ai/)). Read on to learn more.
> **Tip**
>
> The feature is available **on all subscription plans** including the Free plan.
## **Generating content for your Softr app**
Whenever adding an image to a block in your Softr app, you can use the Asset Generator to generate an image for you. The following videos show how that works.
Similarly, on any text field you have the option of adding AI-generated copy by providing a helpful prompt. The video below illustrates the process.
## **Allowing your users to generate content**
You can also allow your users to generate images and copy using the AI Dynamic Blocks. Just add one of the blocks to your app and make the magic available to your users. To make this happen, you first need to integrate with Open AI, which we’ll discuss in a bit.
## Sending custom prompts to OpenAI
Want to take one step further? Check out Softr Community member Dominic's video on how to integrate GPT-3 with Softr.
## Integrating with Open AI
To integrate Open AI with your Softr app, you need to go to and sign up. Next, under your account dropdown, select **View API keys**.

_View API keys_
Hit **Create new secret key** and copy the generated key.

_Create new secret key_
Lastly, in your Softr app, navigate to **Settings ⇒ Integrations ⇒ Open Ai**, add the key, and save your settings.Now, you can start adding AI blocks to your application.
When you register on Open AI, you automatically enter a free trial, so, as soon as a user submits the first request (e.g. generates a text using the block), you’ll see your Open AI credit balance under **Usage**.

_Open AI Usage_
You’ll spend credits on each new user request, so, as soon as all the free trial credits expire, you’ll need to Upgrade your Open AI subscription in order to receive more credits.
---
# Google Sign-in
Source: https://docs.softr.io/integrations/google-sign-in
Google Sign-in puts a **Continue with Google** button on your app's sign-in and sign-up forms. People who already have a Google account get in with one click, and you never hold a password for them.
Setting it up happens in two places: you create an OAuth client in the Google Cloud console, then paste its client ID and secret into Softr. Keep both tabs open — you will be moving between them.
> **Note**
>
> Google Sign-in is one of the methods on the [sign-in form](/add-and-manage-users/signin-form), alongside email and password. It is not the same as [SSO](/add-and-manage-users/single-sign-on-overview), which hands authentication to your own identity provider over SAML or OpenID. You can switch both on at once.
## Before you start
**A Google account that can create Cloud projects**
Creating a project needs the `resourcemanager.projects.create` permission. Personal Google accounts have it; a work account in a Google Cloud organization often does not, and the **No organization** row in the project picker will be marked with a warning triangle. If that happens, ask whoever administers your Google Cloud organization to create the project — or to grant you the permission — and carry on from step 2.
**Your app's URL, exactly as visitors see it**
Open your published app and copy the address out of the browser bar. On a Softr subdomain that is `https://yourapp.softr.app`, with no `www.`; on a [custom domain](/publishing/add-a-custom-domain-to-your-app) it is whatever host you connected. You need the scheme and host only — no trailing slash, no path.
## Create your Google OAuth client
1. **Create a Google Cloud project**
In the [Google Cloud console](https://console.cloud.google.com/projectcreate), give the project a name. Google derives a project ID from it, which cannot be changed later. If your account belongs to an organization you also have to pick a **Parent resource**. Click **Create**.

_Naming a new project in the Google Cloud console._
> **Tip**
>
> Already have a project for this app? Skip this step and pick it from the project picker in the console's top bar instead.
2. **Name the app people will consent to**
Go to **Google Auth Platform → Branding**. **App name** and **User support email** are what people see on Google's consent screen the first time they sign in, so use the name of your portal rather than the project ID. Click **Save**.

_App name and support email on the Branding page._
> **Note**
>
> On a brand-new project, opening Google Auth Platform starts a short **Get started** wizard that asks for the app name, support email, audience and a contact address in one pass. Complete it and you arrive at these pages with the work already done. Google documents the rest of the branding options in [Manage OAuth App Branding](https://support.google.com/cloud/answer/15549049).
3. **Choose who can sign in — and publish the app**
Open **Audience**. Two settings on this page decide who gets in.

_Publishing status and user type on the Audience page._
1. **Publishing status.** A new project starts in **Testing**, and while it is in Testing only the Google accounts listed under **Test users** can sign in — up to 100 of them. Click **Publish app** to move it into production.
2. **User type.** **External** lets anyone with a Google account sign in. **Internal** appears only if your Google account belongs to a Google Workspace organization, and limits sign-in to that organization.
> **Warning**
>
> Leaving the project in **Testing** is the most common reason a correctly configured Google Sign-in still fails: everyone who is not on the test-user list is refused. Publish the app before you point real users at it. Google's [Manage App Audience](https://support.google.com/cloud/answer/15549945) covers the limits in full.
Note which **User type** you picked. You set the same value on the Softr side.
4. **Create the OAuth client**
Go to **Clients → Create client**. Set **Application type** to **Web application** and give the client a name. The name is only used to identify the client in the console; nobody signing in ever sees it.

_Choosing the Web application client type._
5. **Add your app's URL to both lists**
Under **Authorized JavaScript origins**, click **Add URI** and paste your app's URL. Then do the same under **Authorized redirect URIs**. Click **Create**.

_The same app URL added as a JavaScript origin and a redirect URI._
> **Note**
>
> Match the origin your visitors actually load, character for character. A Softr subdomain has no `www.` — `https://acme-portal.softr.app`, not `https://www.acme-portal.softr.app`, which does not resolve. On a custom domain, include `www.` only if that is the host people land on.
> **Tip**
>
> Google registers the domains of these URIs as **Authorized domains** on your consent screen automatically, so there is no separate step for that. Changes to a client can take anywhere from five minutes to a few hours to take effect.
6. **Copy the client ID and secret**
Google shows the new client's ID and secret as soon as it is created. Copy both before you close the panel.
> **Warning**
>
> Google no longer lets you view a client secret after creation — the client's page shows only its last four characters. If you lose it, open the client and use **Add secret** to issue a new one, then update Softr with the new value.
## Add the credentials to Softr
1. **Switch Google Sign-in on**
In Softr Studio, open your app and go to **Users → Authentication**. Turn on the **Google Sign-in** toggle (1), then click the gear (2) to open its settings.

_The Google Sign-in row in the Authentication method list._
> **Note**
>
> An amber dot next to a method means **Setup is incomplete** — it is switched on but has no working configuration yet. It clears once you save valid credentials.
2. **Paste the credentials**
Paste the **Google client ID** and **Google client secret** you copied from the console (1). Then set **User type** (2) to the same value you chose on the Audience page.

_The Google Sign-in settings dialog with Internal selected._
With **Internal**, a **Google Sign-in email domains** field appears. Anyone whose email address is on one of these domains is always sent to Google to log in, even when your app also offers email or SSO. Choosing **External** hides the field, because an external client accepts any Google account.

_With External selected, the email domains field is not shown._
3. **Save and publish**
Click **Save**, then publish your app so the change reaches the live site. The amber dot beside **Google Sign-in** should disappear.
## What people see
**Continue with Google** appears above the email field on both the sign-in and the [sign-up form](/add-and-manage-users/signup-form). The first time someone uses it, Google shows a consent screen carrying the app name and support email you set under **Branding**.

_The Continue with Google button on a published app's login page._
Signing in this way creates or matches a record in your app's [users list](/add-and-manage-users/users-menu) on the email address the Google account carries.
## Troubleshooting
**Google refuses the request before showing the account chooser**
The URL registered on the OAuth client does not match the address the browser is on. Compare them character for character: `http` against `https`, `www.` present or absent, and no trailing slash. If you have just changed the client, give it a few minutes — Google warns that client changes can take up to a few hours to propagate.
**Some people can sign in and others cannot**
Either the Google Cloud project is still in **Testing**, in which case only the accounts on the test-user list are allowed, or the client's **User type** is **Internal** and the people being refused are outside your Google Workspace organization. Both live on the **Audience** page.
**The amber dot beside Google Sign-in will not clear**
Softr marks a method **Setup is incomplete** until it has a client ID and secret saved. Reopen the gear and check both fields are filled and saved.
**Only people on certain domains are sent to Google**
That is the **Google Sign-in email domains** field doing its job. Clear it if you want those people to be able to use email or SSO as well.
## Related
[**Sign-in form**](/add-and-manage-users/signin-form)
Every authentication method your app can offer, and how the form behaves.
[**Single Sign-on Overview**](/add-and-manage-users/single-sign-on-overview)
SAML and OpenID, for when authentication should sit with your own identity provider.
[**Internal vs external users**](/add-and-manage-users/internal-vs-external-users)
How Softr counts the people who sign in to your app.
[**Google: set up OAuth 2.0**](https://support.google.com/cloud/answer/15549257)
Google's own reference for OAuth clients, consent and credentials.
---
# Make
Source: https://docs.softr.io/integrations/make
## "Send to Make" Action
The Make integration is available through a **Send to Make** action, which is available as a [Form](/4876cbed455842aebe38e0612d2da96e) submit button action. When you create a form, set the destination of the form response to be Make.

_“Send to Make” action_
After selecting Make from the dropdown, another field will appear where you will place a Make Webhook URL. More on that below:

_Custom Webhook URL field_
Here, you need to fill in a **Custom Webhook URL** to connect to Make. So, let's switch to Make to configure our automation and get the **Webhook URL**.
## Creating a Scenario in Make
In your Make account, you should create a new **Scenario**, set up a **Webhooks** app, and choose the **Custom Webhook** trigger. As soon as the **Custom Webhook** is ready, you need to hit **Copy address to clipboard** to get the **Webhook URL**. Below you can see how that's done.

_Setting up a Custom Webhook trigger and getting its URL_
## Adding the Webhook URL in Form Settings
Now, you need to run your Make scenario and go back to your Softr form to enter the **Webhook URL**. After entering the URL, use the link below to **Send test data**. Further on, if you go back to your Make scenario, you should see a notification on top of your webhook icon. Click on it to see the content of the bundle that has been received. If your test data has arrived successfully, you can now add new modules to your webhook to receive the data on other services.

_Adding the URL and testing the integration_
> **Warning**
>
> IMPORTANT: When sending a test call to the webhook from Softr Studio, not all fields will be sent from the Softr form to the Webhook - only some test fields will be sent. In order for Make to properly identify the correct data structure you will use in production, you should submit a form response from the live app or app preview while the webhook is listening.
## Sending Data to Trello
Now, you need to connect another service to send the data to. Let's assume you've set up a simple contact form and want to send the form submissions to the [Trello](https://trello.com/) task management tool, creating a new card on the board for each submission.

_A simple contact form_
Therefore, you need to click **Add another module** on your custom webhook and search for **Trello** within the new module.

_Adding a Trello module_
Configuring Trello Account and Mapping the Fields
After selecting Trello in the list, scroll down and choose **Create a Card** action.

_“Create a Card” action for Trello_
In the next step, you need to connect your Trello account, clicking the **Add** button under **Connection**. Afterwards, under **Enter a List ID** you can either enter your Trello **List ID** manually or choose **Select** to be provided with the list of your current boards and their lists to choose from.

_Connecting Trello account and board/list_
After setting the board and list you want the cards to be created on, you need to scroll down and map the form fields. In the example below, we've mapped the **Email** field to the card **Name**, and the form **Name** and **Message** fields to the card's **Description**.

_Mapping form fields to Trello_
## Testing the integration
That's it. Now, let's run our Scenario and do a test submission from our Softr form to make sure the data is being received on Trello.

_Testing the Automation_
> **Tip**
>
> Note: When sending a test call to the webhook from Softr Studio, not all fields will be sent from the Softr form to the Webhook - only some test fields will be sent. In order for Make to properly identify the correct data structure you will use in production, you should submit a form response from the live app or app preview while the Webhook is listening.
---
# Zapier
Source: https://docs.softr.io/integrations/zapier
## "Send to Zapier" Action
The Zapier integration is available through a **Send to Zapier** action, which can be selected for the [form](/4876cbed455842aebe38e0612d2da96e) submission button.

After selecting the action, a field titled **Zapier** will appear below. Here, you will need to add the **custom webhook URL**, which we’ll discuss shortly.

_Custom webhook URL_
> **Tip**
>
> Please, note that if you have a **File** field in your form, the attached file(s) won't be transferred to Zapier. As a workaround, we'd suggest using links (e.g. a Google Drive link) for sending files.
## Creating a ZAP
Next, you need to go to your Zapier account and hit the **MAKE A ZAP** button in the upper left corner.

_“Make a Zap” button_
In the app event search bar, look for the **Webhooks by Zapier** app and select it.

_Locating “Webhooks by Zapier”_
Then, select **Catch Hook** as a **Trigger Event** and hit **Continue**.

_“Catch Hook” trigger event_
In the following step, you’ll get a **Custom Webhook URL**, which you need to copy and add it back in the Zapier field of your button action.

_Getting Custom Webhook URL_
## Entering the URL back in Softr Studio
Navigate back to Softr Studio, enter the copied URL as a value in the Zapier field.

_Entering Custom Webhook URL_
Now, you can click to send test data to make sure it's working.

_Sending test data_
## Checking the Results in Zapier
After sending test data, go back to your Zap setup and proceed to the next step. There you should see a **Test trigger** button.

_Testing the trigger_
If after hitting the button your request is found, as shown in the screenshot below, then the integration has been successful, and the only thing left is to click **Continue** to go to the next step in your Zap setup and configure the application to which you want your data to be sent to.

_Test trigger success_
## Sending Data to Google Sheets
In the next step, you need to define the action that the zap needs to accomplish. Let's assume, we want to send the form data to Google Sheets, creating a new row within the sheet for every submission. If for instance, we use the Simple Contact Form, we should have corresponding columns in the sheet to map the fields.

_A contact form on Softr_

_Corresponding fields on Google Sheets_
So, in the next **Action** step, we need to choose the Google Sheets app, set **Create Spreadsheet Row** as an **Action Event**, and hit Continue.

_Selecting Google Sheets under Action_

_Choosing an event_
In the next step, you need to add your Google account (if it hasn't been added yet) to get access to Google Sheets.

_Connecting Google Sheets account_
In the next step, you need to add the Google drive where your spreadsheet is located, and select the spreadsheet and worksheet you want to send the data to. Lastly, you need to map the form fields to the corresponding worksheet columns, as shown below.

_Adding Google Sheets details_
## Testing the integration
Proceed to the next step, and you're almost done. You just need to test the action to make sure it's working correctly.

_Running a test automation_
If the test was successful, you should see a success message in the next step and your spreadsheet should be updated with the test data, as shown below.

_Test submission received_
The form is now linked to the spreadsheet and you can start receiving submissions.
---
# Iubenda Cookie Solution
Source: https://docs.softr.io/integrations/iubenda-cookie-solution
Iubenda Cookie Solution allows to add a customizable cookie consent banner on your site. You will need an Iubenda subscription for this integration. Let's see how it can be done.
> **Tip**
>
> By default, Iubenda will block the most common scripts on your site until the user hits **Accept**. More details on privacy controls and cookie solution configuration are available [here](https://www.iubenda.com/en/help/1205-how-to-configure-your-cookie-solution-advanced-guide).
## Generating a Banner
In your Iubenda account home page, click the **Start Generating** button.

_Start generating_
Choose the **Website** option, specify a **Site Name**, and hit **Start Generating**.

_Choosing the “Website” option_
Next, locate the **Cookie Solution** option and click **Generate Now**.

_Generating the code_
In the following page, you can customize your banner's design and configure other settings. Hit **Next** as soon as you're done.

_Customizing the banner design_
Next, if you don't have a paid license, you'll see a pop-up with the upgrade options. You don't need a paid license for the cookie solution, so, if you don't want to upgrade at this point, simply close the pop-up.

_Closing the upgrade pop-up_
## Getting the Banner Code
Now, you should see an **Embed** button under **Cookie Solution**. Click the button to get the banner code.

_Getting the embed code_
Here, you can enable/disable **Prior blocking and asynchronous re-activation** and customize the banner further if needed. When everything is ready, simply click **Copy** to copy the banner code.

_Accessing the embed code and customizing the banner further_
## Adding the Banner Code in Softr Studio
Now, switch to your Softr Studio, navigate to **Settings => Integrations => Iubenda Cookie Solution,** and paste the code.

_Applying banner code in Softr_
You're almost done. Just save the settings and republish your app, and you'll notice the cookie consent banner appearing.

_Iubenda pop-up published on the Softr app_
---
# Documint
Source: https://docs.softr.io/integrations/documint
With Softr x Documint integration, you can generate documents directly from your dynamic blocks connected to [Airtable](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX). For more info, please visit [this page](https://docs.documint.me/integrations/softr).
---
# Mailchimp
Source: https://docs.softr.io/integrations/mailchimp
Using Mailchimp you can collect email addresses from your audience, who fill out email capture forms on your website. All email addresses will be sent to and stored in your Mailchimp account.
## **Configuration**
When you use a building block with email capture form (e.g. [Hero section with email capture](/59b829b4b58f417fa4b6cff5f7c6a658)), you will see the following options in the sidebar to choose from.

_List of action options_
Choose the **Add to Mailchimp** option to collect emails via Mailchimp. After selection, you will see the **Action Url** field appear.

_Mailchimp action URL_
You need to locate the **Action Url** from your Mailchimp account, and copy paste it in this field.
## **How to locate Mailchimp Form Action Url**
In order to get an Action URL and start collecting subscriptions, you need to log into your Mailchimp account and navigate to **Signup Forms ⇒ Embedded Forms**.

_Embedded forms_
The embedded form will only have the email field enabled by default, so, if you’re just collecting emails, you don’t need to change anything (we’ll discuss setting up forms with multiple fields in the next section). Just hit **Continue** to proceed to the final step.

_Continue_
In the next screen, copy the form **Action URL** (as shown below), then go back to your Softr application and paste it in the **Action URL field** of your form. That’s it. Now, all the emails submitted from your Softr app will be collected in your Mailchimp account under **Contacts**.

_Getting the action URL_
> **Tip**
>
> If you're testing the form submission and not getting anything on Mailchimp, that could be due to **Double Opt-In** being enabled in your Mailchimp settings. When it's enabled, the user that submits the form receives a confirmation email. Only after the submission is confirmed by the user, it is sent to Mailchimp. You can find more details [here](https://mailchimp.com/help/about-double-opt-in/).
## Connecting custom forms to Mailchimp
Let’s create a [Customizable Form](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/advanced-form-features/jCim5VWZePgZuaRsUZBnpG) on Softr with multiple fields and see how we can connect it to Mailchimp to collect all the submissions there.

_Customizable form on Softr_
So, we are going to create a form with three fields (**Email**, **First name**, and **Last name)** and set the destination to Mailchimp.

_Setting form destination_
Now, we need to add the **Action URL**. To get the action URL and receive form submissions on Mailchimp, we need to create a similar form in our Mailchimp account. First, we need to create an **Embedded Form.**

_Embedded forms_
Next, in form settings, we are going to navigate to **Form Fields** and enable two additional fields apart from **Email**. Below, you can see how we’ve enabled three fields, creating a form similar to what we have in our Softr app.

_Creating a form with additional fields_
Lastly, we are going to hit **Continue** and copy the **Action URL** on the next screen, which we’ll need to paste in our form settings on Softr.

_Getting the action URL_
But that’s not all. In order to map all the form fields correctly from Softr to Mailchimp, we also need to specify a **Map to** value for each field. Those values can be found in the same embedded form code under **name**. Below, we’ve located the name of the **First name** field.

_Name of the field_
You should copy the values for all your fields (including the **Email** field) and add them to your Softr form for each field under **Map to**.

_Filling in the “Map to” value_
And we’re done. Let’s do a test submission to make sure it works correctly.

_Doing a test submission_
---
# Mailerlite
Source: https://docs.softr.io/integrations/mailerlite
With MailerLite you can collect emails from your users through any email capture form. All the collected emails will be sent to and stored in your MailerLite account.
## **How to integrate MailerLite with Softr**
MailerLite integration can be applied to any block with email capture (CTA, Hero section, Form etc). For instance, if you are configuring a [CTA with email capture](/6772b65a34c84bfdbe1bc16e8b03f525), you will see an "Add to Mailerlite" option under the submit button's **Action.**

_“Add to Mailerlite” action_
As soon as you choose this option, a new field will appear, where you need to provide the MailerLite **Action URL** to link the email capture form to your MailerLite account.

_“Action URL” field_
So, let's see how you can get the **Action URL** from MailerLite.
## **How to locate MailerLite Action URL**
1. **Create a Subscribers Group**
Log into your MailerLite account, go to **Subscribers => Groups**,and create a group (or use an existing group if you already have one).

_Creating a group_
2. **Create an embedded form**
Then go to **Forms => Embedded Forms** and create an embedded form as shown below.

_Creating an embedded form_
3. **Select a Subscribers Group for the Form**
After entering a name, you'll see the next step, where you need to select the Subscribers group for the form. Choose the group where you want the contacts to be stored and hit **Continue**.

_Selecting a Subscribers Group_
In the next screen, just hit **Done Editing** to finalize the form.

_Finalizing the form_
4. **Getting the Action URL of the Form**
Finally, you'll be taken to your form's **Overview** page, where you should scroll down to the **Embed form into your website** section and switch to the **HTML code** tab. Here, you need to locate the action URL of the form (can also search for "action" using browser search with Ctrl+F), and copy the URL (highlighted below).

_Getting the Action URL_
5. **Adding the URL on Softr**
Lastly, you just need to add the URL in the **MailerLite** field of your Button.

_Adding the Action URL_
That's it. You can now publish your form and start collecting subscriptions. See how that works below.

_Testing the email capture_
> **Tip**
>
> If you're testing the form submission and not getting anything on MailerLite, that could be due to **Double Opt-In** being enabled in your Form settings. When it's enabled, the user that submits the form receives a confirmation email. Only after the submission is confirmed by the user, it is sent to Mailerlite. You can find more details on that [here](https://www.mailerlite.com/help/how-to-use-double-opt-in-when-collecting-subscribers).
## Sending forms to MailerLite
In the previous section, we discussed how to capture emails with MailerLite, however you might also need to map a whole form with multiple field. Let's say you have a [Customizable Form](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/advanced-form-features/jCim5VWZePgZuaRsUZBnpG)
on Softr with the following fields: **Name**, **Email**, and **Message**.

_A Customizable Form on Softr_
In order to receive the form submissions on MailerLite, you should build a similar form there as shown below.

_A custom form on Mailerlite_
Next, in the form configuration page, you need to go to the **HTML code** tab of the **Embed form into your website** section and, apart from grabbing the **Action URL** of the form, you should get the names of corresponding fields (e.g. **fields\[name]** for the **Name** field as shown below).

_Getting field names_
These names need to be pasted inside the **Map to** parameter of each of the form fields.

_Mapping the form fields_
As soon as you do the same for the rest of the fields and add the **Action URL** (discussed in the previous section on email capturing with Mailerlite), you're all set. Now, you can start receiving form submissions on MailerLite. Let's test the form to see how that works.

_Testing the form submission_
---
# Typeform
Source: https://docs.softr.io/integrations/typeform
In this tutorial, we'll go through the process of adding a [Typeform](https://www.typeform.com/) form on a Softr app.
## Getting the form embed code
In your Typeform account, open the form that you want to add to your site, and hit **Share** in the top navbar.

_Share form_
Further on, you need to choose the **embed mode**, and you can also configure the design and some advanced settings (each mode has its specific settings).

_Embed mode_
As soon as the embed is ready, hit the **Get the code** button and copy the embed code, which you'll then need to add to your Softr app. The next section shows how to add the embed code for all the modes except the **Full-page** mode. For adding a **Full-page** code, please proceed to the corresponding section further in this article.
## Adding the Embed Code
The embed code can be added inside a [Custom Code](/custom-code/3idxDhKqz1qPdqBuWbs61G/custom-code-block-overview/6XNrxFopUEiwbWipq81Eq1) block. You just need to paste the code inside the block as shown below.

_Adding embed code inside the Custom Code block_
## Adding a Full-Page Embed Code
If you want to add a Full-page Typeform embed, you can use the [Custom Code](/custom-code/3idxDhKqz1qPdqBuWbs61G/custom-code-block-overview/6XNrxFopUEiwbWipq81Eq1) section inside **Page Settings**. Just paste the code inside the **Header** or **Footer** area.

_Adding the code to a page_
---
# Crisp
Source: https://docs.softr.io/integrations/crisp
## Adding your website
To integrate Crisp on your Softr app, you need to add your site domain and name when registering on Crisp or in **Settings => Website Settings => Add a new website**.

_Add a new website_
Add your website details as shown below.

_Adding website details_
## Getting the website ID
As soon as your site is set up, go ahead and connect Crisp. First, you need to click **Integrations**
next to your site name in **Settings => Website settings**.

_Integrations_
In the pop-up that appears next, choose the **HTML** option.

_Selecting the HTML option_
In the HTML code, locate the **Website ID** and copy it.

_Locating Website ID_
## Adding the Website ID in Softr Studio
Finally, go back to Softr Studio and paste the code in **Settings => Integrations => Crisp**.

_Adding Website ID in Softr_
Save the settings, publish your app again, and you’re done. Now, the Crisp chat icon should appear on your site, allowing your customers to contact you at any time.

_Crisp Chat activated on the site_
---
# Drift Chat
Source: https://docs.softr.io/integrations/drift-chat
##
Here we’ll go through the process of adding the Drift widget to your site. In your Drift account, you need to go to **Settings => Drift widget**, scroll down to **Install**, and locate the **JavaScript** option.

_Drift widget setup_
Hit **Copy** to copy the JavaScript code.

_Copying the JS code_
In your Softr Studio, go to **Settings => Integrations => Drift Chat** and paste the code inside the field.

_Adding Drift widget code in Softr_
That’s it. As soon as you save the updated settings and republish your app, you’ll see the Drift widget appear on the site, as shown below.

_Drift widget published on site_
---
# HubSpot Chat
Source: https://docs.softr.io/integrations/hubspot-chat
## Creating a Chatflow
To add a chat widget to your Softr app, you first need to create a chatflow in your HubSpot account to be able to receive messages. To do that, go to **Conversations => Chatflows => Create chatflow.**

_Creating a Chatflow_
In the next step, choose **Website**.

_Choosing the “Website” option_
Then select **Live chat**.

_Selecting the “Live chat”option_
Next, select the **Inbox** and a **Language** for the chatflow, and hit **Create**. You can find more info on configuring these and other parameters of the chatflow [here](https://knowledge.hubspot.com/chatflows/create-a-live-chat).

_Selecting Inbox and Language_
Lastly, you enter the edit page where you can [customize](https://knowledge.hubspot.com/chatflows/create-a-live-chat) your chatflow, and, as soon as you are done, enable it in the upper right corner of the page.

_Enabling chatflow_
So, your chatflow is ready, and you can go ahead and add the tracking code in your Softr app to start displaying the chat widget to your visitors.
## Getting the Tracking Code
Go to **Settings** in your HubSpot account.

_Accessing settings_
Scroll down to **Tracking Code** and copy the **Embed code**.
> **Tip**
>
> The location of the tracking code can be different depending on your HubSpot subscription plan. Check out this [article](https://knowledge.hubspot.com/reports/install-the-hubspot-tracking-code) for more details.

_Getting the tracking code_
## Adding the tracking code in Softr studio
In Softr Studio, go to **Settings => Integrations => HubSpot Chat**, and enter the **Tracking Code**.

_Adding the tracking code in Softr_
Save the **Settings**, republish your app, and you're done. Now, the chat widget should start appearing on your site.

_HubSpot chat widget added_
---
# Intercom
Source: https://docs.softr.io/integrations/intercom
Intercom is a messaging platform that allows you to communicate with prospective and existing customers. Here, we'll go through the process of adding the Intercom chat widget to your Softr app.
## Locating Intercom Workspace ID
First, you need to locate your Intercom **workspace ID** (app ID). It can be found in the URL of any page you have open in Intercom. It's the code that comes after **apps/**.

_Locating the workspace ID_
The workspace ID can also be found in Settings. In your Intercom account, hover over the account icon in the lower left corner and go to **Settings**.

_Navigating to Settings_
Then go to **Installation => Web** and choose the **With code** option under **Install chat for visitors.**

_Widget installation_
Scroll down and copy the **app\_id**.

_Copying app ID_
## Adding Workspace ID in Softr Studio
So, after copying the workspace ID, navigate to **Settings => Integrations => Intercom** in your Softr Studio and paste the ID.

_Adding Intercom ID in Softr_
That's it. As soon as you save your settings and republish your Softr app, the Intercom chat widget will start appearing.

_Intercom widget added to site_
---
# Google Maps
Source: https://docs.softr.io/integrations/google-maps
You can add a Google Map to your application using the [Contact form with Map](/79a9d5f0f13c4e14a510db94242e668c) or the [Map](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/map/e1zLdwuFNU7A9WakvLBHsq) block. Here are the steps to do that:
## ****Step 1: Get the API key****
To use the Maps in your application you must have an API key. The API key is a unique identifier that is used to authenticate requests associated with your application for usage and billing purposes.
Go to this page and follow the instructions described in [Google documentation](https://developers.google.com/maps/documentation/javascript/get-api-key?hl=en).
## ****Step 2: Copy the API key****
Copy the API Key created for your project (Note: you need to create a new project if you don't have one).
## ****Step 3: Apply the API key****
Go back to your Softr app and add the key in [Settings](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/general-settings/7YdGy1J8X2tjJSv8BGvWQU) ⇒ Integrations ⇒ Google Maps Integration as shown below.

_Adding the map API key_
Now, you can go to your map and start configuring it.
---
# AtomChat
Source: https://docs.softr.io/integrations/atomchat
AtomChat is a great solution for adding a group chat or video conferencing functionality for your users if you're building an online community, a social network, an internal collaboration tool, and so on.
[Here](https://help.atomchat.com/portal/en/kb/articles/add-atomchat-to-your-softr) you can find a detailed step-by-step guide on integrating AtomChat with Softr. You can also [add a chat option directly to user profiles](https://help.atomchat.com/portal/en/kb/articles/chat-with-a-user-from-their-profile-softr).
---
# Stripe Checkout
Source: https://docs.softr.io/integrations/stripe-checkout
With Stripe Checkout’s serverless integration for simple one-time payments or recurring subscriptions, you are able to charge your customers with a click of a button.
## **Connecting Stripe**
Connecting to Stripe requires you to have an account on Stripe. If you don't have an account yet or new to Stripe, please get yourself familiar with the [Stripe documentation](https://stripe.com/docs) first.
After making sure you have a [Stripe account](https://stripe.com/docs), [Products](https://stripe.com/docs/billing/subscriptions/set-up-subscription#without-code) & [Pricing Plans](https://stripe.com/docs/billing/subscriptions/set-up-subscription#without-code) defined, proceed with these steps to connect Stripe to your Softr's application.
1. **Step 1:Enable Checkout on Softr Side**
To enable checkout on Softr side, you need to first add your Stripe's authentication keys to Softr. You need to navigate to the API keys page on your Stripe checkout and copy the **Publishable key** and **Secret key** to your Softr app's **Settings => Integrations => Stripe Checkout** page as shown below.

_Adding Stripe authentication keys on Softr_
2. **Step 2:Add a Checkout to your Application**
To collect payments from your users, you can either use the [Simple Checkout Form](/integrations/etS18kJqm1fuD58KCsjC3z/simple-checkout-form/tKt3f5cV2CxsFLGM1aaNYX) or link to a Stripe checkout from your site (e.g. using the [Pricing block](/integrations/etS18kJqm1fuD58KCsjC3z/layout-pricing-in-card-view-with-details/pNspR4mKu6spj1KSzRf4p7)).
You can also add a [Simple Billing Form](/integrations/etS18kJqm1fuD58KCsjC3z/simple-billing-block/9oj8iqzqLhBWFHVt2UAY1K) or connect a [Stripe Custome Portal](/integrations/etS18kJqm1fuD58KCsjC3z/stripe-customer-portal/3B7NhNtJ4RvipBwi7FwUtF) to allow your users to view and edit their billing details.
---
# Buy me a Coffee
Source: https://docs.softr.io/integrations/buy-me-a-coffee
Buy Me a Coffee is a simple tool for creators to get paid and connect with their fans. To start receiving payments through Buy Me a Coffee, you just need to provide a link to your Buy Me a Coffee page. There are a few ways to do this, which we'll examine below.
## Profile Link
You can copy the link to your profile from your Buy Me a Coffee account's dashboard and put it as an **External URL** under any button in Softr Studio. See below.

_Adding a link to a Buy Me a Coffee profile_
## Buy Me a Coffee Button
You can generate a button in your Buy Me a Coffee account. From your page, navigate to the **Dashboard** and select the **Website Buttons** option. Then, you just need to **Copy code** and place the code inside a [Custom Code](/custom-code/3idxDhKqz1qPdqBuWbs61G/custom-code-block-overview/6XNrxFopUEiwbWipq81Eq1) block in Softr Studio. See how it's done below.

_Adding a Buy Me a Coffee button to Softr_
---
# Gumroad
Source: https://docs.softr.io/integrations/gumroad
Gumroad is an online platform for creators to sell their products directly to consumers. The platform is mostly intended for selling digital content like albums, ebooks, music, tutorials, and so on.
Let's see how you can integrate Gumroad with Softr to start selling. When you create a product on Gumroad, it is assigned a unique link as shown below.

_Getting product URL_
So, when creating a product on Softr, you just need to have a button (e.g. "Buy Now") that will open the corresponding Gumroad product link. In most of the cases, you'll be importing a list of products from Airtable. Let's assume you've created your app based on our e-commerce template (see how to create an app with template Airtable base [here](https://studio.softr.io)).
Thus, you have your products along with their names, images, descriptions and so on. Also, each product has a **View Details** button, which is linked to the item details page. Let's modify the button to open the product's Gumroad page instead.

_“View Details” button on a product_
To achieve that, you need to create a new field in your Airtable base, where each product's Gumroad link will be stored. So, let's add a new column and call it "Gumroad Link.”

_Gumroad link in product list on Airtable_
Now, in your product listing configuration, you need to scroll down to the **View Details**
button, set the **Action** to **Open external url,** and set the Url to the "Gumroad Link" field.

_Configuring the button click action_
That's all. Now, when the users click on the **View Details** button on the product, they'll be taken to the product's Gumroad page.

_Testing the Gumroad setup_
You can also add the Gumroad link on the product details page or anywhere else the same way. You just need to set the button **Action** to **Open external Url** and set the corresponding Airtable field with product links.
Alternatively, you can add the link directly if the product is a standalone item (e.g. you are using a [CTA button](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/cta/oPDoXzSUpMuKki92WuBDDH)), as shown in the example below.

_Add Gumroad link to Softr_
---
# PayPal
Source: https://docs.softr.io/integrations/paypal
You can easily integrate PayPal on your Softr app to start receiving payments. You can either add a single button or, if you're importing a list of products from a [data source](/4230abecf813402aa2926466c313290a), you can add a PayPal link for each product in your database, so that customers can visit your store and make purchases. Let's discuss each case separately.
## Adding a Single Button
Your starting point is where you can choose the type of button you want to have on your site. After generating the button, the code can be added inside a [Custom Code](/custom-code/3idxDhKqz1qPdqBuWbs61G/custom-code-block-overview/6XNrxFopUEiwbWipq81Eq1) block in your Softr app.
As an example, let’s use the **Buy Now** button:

> **Info**
>
> Make sure you are signed in to PayPal to see the Buy Now option.
Follow PayPal’s configuration steps like providing a Product name and Price:

Once done, click “Save and Create Button”:

You will land on a page with your button code. Copy the code:

Finally, add the link to a [Custom Code](/custom-code/3idxDhKqz1qPdqBuWbs61G/custom-code-block-overview/6XNrxFopUEiwbWipq81Eq1) block:

## Adding links in a data source
Let's assume you've created an e-commerce app. Thus, you have your [product listing](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU), and each product has a **View Details** button, which should be linked to the item [details page](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/item-details-block-/4bE8XaFbJp45wkAwuWiz8f). On the details page, there's in turn a **Buy Now** button. So, let's customize the **Buy Now** to link it to the item's PayPal **Buy Now** button.
This time, when you create a button, switch to the **Email Link** tab, and copy the code.

### **Adding the Button Link to the Product**
Now, you have the button link and need to add it to your data source to the corresponding product. We are going to use [Airtable](/data-sources/1YYStCJukT15Lh2j93qo9A/airtable/jHX7kfH7QvkVcELQvS3VoX) as our data source and create a **PayPal Link** field to add the button link there.

_The “PayPal Link” field on Airtable_
Next, on our product details page, we are going to set the **Buy Now** button action to **External url** and select the **PayPal Link** field.

_Setting the external URL to the PayPal link field_
So, that's the process for one particular product, and you need to repeat it for all the products, creating a unique PayPal button for each one. When you're done, the Buy Now button on the product page will redirect to the PayPal payment page, as shown below.

_Testing the button_
---
# Layout: Pricing in card view with details
Source: https://docs.softr.io/integrations/layout-pricing-in-card-view-with-details
Using this block, you can display the different pricing options of your product or service. You can also link each option to a corresponding checkout page (internal or external), which we'll discuss a bit later.

_Pricing in card view with details_
Let's review the block settings, which are located under the **Features** tab.
## **Title and Subtitle**
Here, you can customize the **Title** and **Subtitle** of the block.
## **Multiple billing cycles**
You can enable this option if, for instance, you want to show different prices for **yearly** and **monthly** billing. Under **Cycle description**, you can add a custom text for your Yearly option.
## **Pricing Tiers**
Here, you add the details for each of your pricing tiers (Title, Yearly and Monthly prices, Features, etc.).
## **Button**
Each tier has a button that can be used to take the users to the checkout page. If you're using a payment service other than Stripe, you can use the **Redirect to url** option under **Add action** to take the users to your external checkout page.
To use the Stripe Checkout option, your first need to [connect your Stripe account](/integrations/etS18kJqm1fuD58KCsjC3z/stripe-checkout/iBomMEucRZtM2y6HuutYVC) to your Softr app.

_Button action options_
**So, let's select the Stripe Checkout option and start configuring the checkout settings.**
## **Recurring payments**
Enable this if you want to charge your customers periodically based on a specific schedule (e.g. for a monthly subscription). When configuring a product on Stripe, you have the option to set it as **One time** or **Recurring**.

_Choosing a product type on Stripe_
## **Allow promotion codes**
Here, you need to choose if you're going to accept [promotion codes](https://stripe.com/docs/billing/subscriptions/coupons/codes) on your Stripe checkout.
## **Enable automatic tax**
You can select to apply automatic taxes on checkout, which needs to be configured on Stripe.
### **Adding the Tax feature on Stripe**
First of all, if you don't have the Tax feature enabled on Stripe, you can add it from the Features and Products list as shown below.

_Adding the Tax feature_
Now, the Tax settings will become available from your Stripe settings.

_Selecting Tax settings_
### **Configuring tax settings**
Further on, you need to configure your tax settings, setting up **Default product tax category**, **Tax registration locations**, and others.

_Configuring tax settings_
### **Testing taxes**
That's it. Now when you create a new product (or edit an existing one) on Stripe, taxes will be applied automatically for your selected locations based on the **Product tax category**.

_Creating a product_
Let's also see what this looks like from the perspective of your Softr app users.

_User checkout_
## **Plan IDs and Success/Cancel URL**
Now you just need to configure each plan corresponding to your Stripe products. If you have multiple billing cycles, you need to configure "**Monthly Plan"** & "**Yearly Plan"** fields in Softr. In case of a single billing cycle, you will configure only one **"Plan"** field.

_Plan IDs and Success/Cancel URLs_
You can find the **Monthly/Yearly Plan ID** by navigating to your [Stripe Dashboard](https://dashboard.stripe.com/). On the dashboard, open **Products Menu**, select a specific product, and choose the corresponding Plan ID from the Pricing plans list. In case your Products list or Pricing list is empty, please make sure to follow the [Stripe documentation](https://stripe.com/docs/billing/subscriptions/set-up-subscription#without-code) to create Products & Plans first.
And finally, you need to fill out **"Success Url"** and **"Error Url"** fields, which show correspondingly where will customers be redirected upon completion (or cancellation/error scenario) of the checkout process.
> **Tip**
>
> The **"Success Url"** and **"Error Url"** fields are mandatory and Stripe checkout won't work if they are empty or don't start with either http\:// or https\://.
---
# Stripe Customer Portal
Source: https://docs.softr.io/integrations/stripe-customer-portal
Using this block, you can enable your Softr app users to access their personal portal on Stripe to manage their purchases/subscriptions and payment info. To start with, you need to integrate your Stripe account with your Softr app (find out more details on that [here](/integrations/etS18kJqm1fuD58KCsjC3z/stripe-checkout/iBomMEucRZtM2y6HuutYVC)). Next, you should configure your **Stripe Customer Portal** in your Stripe account. Let's see how that's done.
## Configuring Stripe Customer Portal
To access customer portal settings, you need to navigate to **Settings => Billing => Customer Portal** on your Stripe dashboard. Here you can specify what actions your customer should have access to (e.g. Cancel a subscription, Edit payment method, etc.). We won't go into details here, as you can learn more through Stripe [help docs](https://stripe.com/docs/billing/subscriptions/integrating-customer-portal). Just make sure to hit **Save** after making the changes.
Now, let's see how you can provide your customers with access to the portal.
## Setting up the portal block on Softr

_Stripe Customer Portal Block_
To provide your customer with access to the Customer Portal on Stripe you just need to add the corresponding block somewhere on your Softr app. In block settings, apart from titles and the background image, you need to set up the **Redirect URL**.
> **Tip**
>
> The Redirect URL is the page your users will be taken to after hitting **Return** on their **Customer Portal** page.
You'll see this in action a bit later when we show the whole process from the customer's perspective.
## How Customers Access the Portal
Finally, let's see what the portal looks like from the customer's viewpoint. We are going to log into our Softr app with a user account, purchase a subscription, and try to edit subscription details and access payment info using the Stripe Customer Portal. Let's proceed.
We've set up the checkout using the **Simple Checkout Form** (take a look at the [block docs](/integrations/etS18kJqm1fuD58KCsjC3z/simple-billing-block/9oj8iqzqLhBWFHVt2UAY1K) to see how it should be configured).
> **Tip**
>
> We've used the **Simple Checkout Form** in our example, but you can use any of the payment blocks integrated with Stripe (e.g. [Pricing block](/integrations/etS18kJqm1fuD58KCsjC3z/layout-pricing-in-card-view-with-details/pNspR4mKu6spj1KSzRf4p7)).
So, below you can see how the user purchases a Stripe subscription through the checkout form and then uses the portal block we just set up to access his portal on Stripe and make changes.

_Editing details on Stripe Customer Portal_
Notice that, at the end, when the user clicks on **Return to Softr**, he's taken to the portal page, as we had set it that way (under **Redirect URL**) in portal block settings previously. Nevertheless, the **Redirect URL** can be set to any page in or even outside of your Softr app (just needs to start with **https\://**).
---
# Simple Billing Block
Source: https://docs.softr.io/integrations/simple-billing-block
Using this block, you can enable your users to manage their subscriptions and purchases on your Softr app. So, let's see what the steps are involved in the setup.
## Integrating Stripe
The block is supposed to work with Stripe and get all the purchase and subscription info from there, so, first of all, you need to [integrate a Stripe checkout](/integrations/etS18kJqm1fuD58KCsjC3z/stripe-checkout/iBomMEucRZtM2y6HuutYVC) with your Softr app.
> **Tip**
>
> In our example we are going to use the **Pricing** block along with **Stripe Checkout** integration, which will link your users to a separate Stripe checkout page.
> However, you can also use the [Simple Checkout Form](/integrations/etS18kJqm1fuD58KCsjC3z/simple-checkout-form/tKt3f5cV2CxsFLGM1aaNYX) instead (with or without the Pricing block). All the subscription and purchase info of your users processed through the **Simple Checkout Form** will be available via the **Simple Billing Form**.
## Setting up a pricing block
As soon as you're done with Stripe integration, you can proceed with setting up a [Pricing](/integrations/etS18kJqm1fuD58KCsjC3z/layout-pricing-in-card-view-with-details/pNspR4mKu6spj1KSzRf4p7) block, where you offer your Stripe products/subscriptions to your users.
Below, you can see a product that we've set up on Stripe (available in the **Products** section of your Stripe dashboard).

_A product page on Stripe_
Now, we are going to add this product on our Pricing block in Softr. Below, you can see how it's configured.

_Product added in Pricing block_
As you can see, we've set the **Button** action to **Stripe checkout** and enabled **Recurring payments**, as the product we've added is a subscription. Moreover, we've copied the **Monthly** and **Yearly** price IDs from the product page on Stripe as well as added **Success** and **Cancel** URLs, which are mandatory. You can find more info on configuring the Pricing block [here](/integrations/etS18kJqm1fuD58KCsjC3z/stripe-checkout/iBomMEucRZtM2y6HuutYVC).
Other subscription plans or products on your Pricing block can be configured the same way. You might also need to provide your users with coupon codes. So, let's review that part as well.
### **Adding Coupon Codes**
Coupons can be created under **Products => Coupons**. Further on, you need to add a **Promotional Code** for your coupon, and the **Name** of your **Promotional Code** is what you should give to your users to use on checkout. Below you can see how that's set up.

_Setting up a Coupon and Promotional Code_
We'll use this code ("test1234") later on in this guide when demonstrating the checkout and billing management process from your users' standpoint.
So, now, let's proceed to setting up the **Simple Billing Form**.
## Configuring the Simple Billing Form block
We are just going to add the **Simple Billing Form** block on a separate page and configure it. Let's quickly go through the block settings.

_Simple Billing Form overview_
Above you can see an overview of the block configuration. Now, let's go through each setting in detail.
First, we can customize the block **Title** and set a **Background image**. Next we need to set the page that the user is going to be taken to if he/she wants to change the subscription plan (**Change plan**). In our case, it's the page with the **Pricing** block, which we configured above.
### **Invoices**
Next up we have the **Invoices** toggle, which allows the users to view all their invoices (fetched from Stripe).
### **Cancel Subscription**
We can also allow the users to cancel their subscriptions at any time. If we enable this option, a number of other fields appear below, where we can customize the section's title and descriptions as well as what appears on the confirmation pop-up.
Now that we've reviewed the configs from the site owner's perspective, let's see how everything looks from the site users' standpoint.
## Billing Management from the User's Perspective
Below you can see how the user purchases a subscription through the **Pricing** block and is later on able to view his/her subscription along with additional info (e.g. Invoices) using the Simple Billing block as well as cancel the subscription. The user also applies a promotional code during checkout.
> **Tip**
>
> In our example, we've used a subscription-type product from Stripe, but one-off purchase products can be set up in a similar manner.

_Checkout and billing management_
As you can see, after completing the checkout, the user is automatically taken to the page with the **Simple Billing Form**, where he/she can manage his/her details.
---
# Simple Checkout Form
Source: https://docs.softr.io/integrations/simple-checkout-form

_Simple Checkout Form_
Using this block, you can set up paid membership and charge your users for accessing certain sections (pages or blocks) of your Softr app. Prior to setting up this block, you need to [connect Stripe](/integrations/etS18kJqm1fuD58KCsjC3z/stripe-checkout/iBomMEucRZtM2y6HuutYVC) to be able to offer Stripe products (one-time products or subscriptions) to your users. So, let's go ahead and examine the block settings.
## Title and images

_Logo, Title, and Background Image_
To start with, you can add a custom title, logo, and a background image in the **Feature** tab of block settings.
## Product Setup
Next, you need to set up the product that you want to offer to your users.

_Product parameters_
The **Product** dropdown is a list with all your Stripe products. First you need to select a certain product, then fill out the rest of the product fields (**Name, Trial, Price, Interval, Description**) as you wish them to be shown on your checkout page. In the example shown below, we've chosen the **Maker (Website Builder)** product, and set the other fields to their corresponding values.

_Product selection_
Below, you can see how it looks on the actual checkout form.

_Published checkout form_
### Payment details
Here, you can customize the placeholder text for the name and email fields.
### Discount code

_Discount Code section_
Here you can choose to show a discount code field. If it's enabled, you can modify the text for the discount button and coupon input field. **The form will accept** **[coupons](https://stripe.com/docs/billing/subscriptions/coupons)** **defined for the selected Stripe product.**

_Applying a discount code_
### Button

_Button settings_
Here, you can modify the **Text** of the payment submissions button. The **Action** of the button is predefined.
### On checkout

_On checkout_
Lastly, you can choose to which page the user is taken after making the payment.
That's it. As soon as you have provided a checkout for a specific product, you can go ahead and define access conditions (for a [block](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/block-visibility/3spA2dfQNrcGcPNmnDXHB3) or a [page](/user-groups-and-permissions/3oA6AaFzUiePs2sW2TpYrF/page-visibility/nWJaN689VKA1TUeaEfzK9u)) for users who have paid for the product.
---
# Facebook Pixel
Source: https://docs.softr.io/integrations/facebook-pixel
The [Facebook Pixel](https://www.facebook.com/business/tools/meta-pixel) is a code snippet placed on your website or web app that lets you track and optimize the audience that visits your site as a result of your Facebook ad campaigns (paid) or organically (unpaid). For instance, if someone lands on your website and then makes a purchase or performs some other action, you can track that activity through Facebook Pixel and tie it to a Facebook Ad. Thus, Pixel tracks all the actions that users make on your website but then ties that traffic directly to an ad if you are running Facebook ads. Then, you can, for instance, retarget your Facebook ads to show them only to your website visitors.
In order to activate the Pixel on your Softr app, you need to locate your **Pixel ID** and add it in **Settings⇒Integrations⇒Facebook Pixel**. Let’s see where you can find the ID.
## Connecting Facebook Pixel
Navigate to Facebook [Ads Manager](https://www.facebook.com/business/tools/ads-manager) and, in the left-hand navigation menu, locate the **Events Manager** tool.

_Navigating to Events Manager_
Next, if you don’t yet have any data connected, a pop-up will appears, prompting you to connect your data. Hit **Connect Data** to continue.

_Connect Data_
Choose the **Web** option and hit **Connect**.

_Connect a website_
Further on, you need to name your Pixel.

_Naming the Pixel_
And also enter your website URL.

_Entering website URL_
In the following screen, you need to choose the connection type. **Conversions API** **+ Meta Pixel** is a more advanced option, and you can learn more about it [here](https://www.facebook.com/business/help/2041148702652965?id=818859032317965). Here, we are going to choose the **Meta Pixel only** option and finalize the setup.

_Connection type_
As soon as you finish setting up your Pixel, you’ll be taken to the **Events Manager Overview**, where you should see all the Pixel-related activity. Here, you need to locate your Pixel ID (shown in the screenshot below) and paste in your Softr app’s **Settings ⇒ Integrations ⇒ Facebook Pixel**.

_Events Manager Overview_
That’s it. Now, you should start receiving activity from your site.
> **Tip**
>
> It can take up to 24 hours before Facebook starts recording activity from the Pixel.
Now, let’s see how you can make sure Pixel is installed correctly on your site.
## Testing Facebook Pixel
If you use Chrome, there’s a handy extensions called [Meta Pixel Helper](https://chrome.google.com/webstore/detail/meta-pixel-helper/fdgfkebogiimcoedlicjlajpkdmockpc) that lets you test Pixel setup on any of your site’s pages. Just activate the extension and open it on any of the pages where you have Pixel installed. Below, you can see how we test it on an app we just installed Pixel on. As you can see, the extension is able to detect the Pixel successfully.

_Testing Pixel setup_
## Tracking more events
What we just did is just the basic setup of Facebook Pixel. However, you can do much more with it, adding [standard and custom events](https://www.facebook.com/business/help/964258670337005?id=1205376682832142) to track such actions as add to cart, purchase, and more.
> **Tip**
>
> You can use the [Header Custom Code](/0392ff65acfe4b1c96923c1aac7982f7) of your Softr page to add the event code.
---
# Google Analytics
Source: https://docs.softr.io/integrations/google-analytics
In this guide, we'll go through the process of integrating **Google Analytics** with your Softr app. You can integrate both **Universal Analytics** and **Google Analytics 4**, and below you can find separate guides for each of the versions.
## Universal Analytics
After [setting up a Google Analytics property](https://support.google.com/analytics/answer/10269537?ref_topic=1009620) for your site, you need to navigate to **Admin**, choose the required property, and click **Tracking Info**, as shown below.

_Locating tracking info_
From the opened dropdown, click on **Tracking Code** and copy the **Tracking ID** (starting with "UA-") as shown below.

That's it, now you just need to paste the ID in **Settings =>** **Integrations => Google Analytics**
in the left-hand toolbar of your [Softr Studio](https://studio.softr.io) and hit **Save.**

_Adding tracking code in Softr_
## Google Analytics 4
After setting up a [Google Analytics 4 property](https://support.google.com/analytics/answer/9304153#zippy=%2Cweb%2Cadd-the-tag-to-a-website-builder-or-cms-hosted-website-eg-wordpress-shopify-etc), you need to go to **Admin**, select the required **property** and navigate to **Data Streams**.

_Accessing data streams_
Next, select the data stream.

_Selecting the data stream_
In the screen that comes next, locate the **Measurement ID** and copy it.

_Getting the Measurement ID_
Finally, you just need to go back to your Softr app and add the ID into [Settings](/application-settings/n3K2UEfpC9BpHgakMzUU5Y/general-settings/7YdGy1J8X2tjJSv8BGvWQU)**⇒Integrations ⇒ Google Analytics** as shown in the following screenshot.

_Applying the Measurement ID_
---
# Google Tag Manager
Source: https://docs.softr.io/integrations/google-tag-manager
The process of integrating Google Tag Manager is pretty straightforward. After creating a container, you just need to locate your **Container ID**. [Here](https://support.google.com/tagmanager/answer/6103696) you can find all the details.
After locating the **Container ID**, you need to copy it and navigate back to your Softr app. Then, you should paste it **Settings => Integration => Google Tag Manager,** and you’re done!

_Adding GTM container ID_
# Alternate Method
> **Tip**
>
> **NOTE:** Do not combine this method with the standard method above. Doing so will cause your tags to trigger twice and you will receive double the data you should.
You can also configure Tag Manager by clicking on the **Settings** icon on the left side of Softr Studio and clicking on **Custom Code.**

_Clicking on settings, then custom code_
Then in a new tab go to [tagmanager.google.com](https://tagmanager.google.com), click on the Account you’ve set up.

_Choose your account from the list_
Then, click on the container ID in the upper right corner.

You will see header and footer codes which can be copied and pasted into the Header and Footer sections of the Custom Code panel of Softr. Don’t forget to click **Save** when finished.

_Custom header and footer code to be copied._

_Be sure to paste the codes in the correct places, then click Save._
---
# Microsoft Clarity
Source: https://docs.softr.io/integrations/microsoft-clarity
[Microsoft Clarity](https://clarity.microsoft.com/projects?utm_medium=partner\&utm_source=Softr\&utm_campaign=Growth) is free analytics tool to help you better understand how your users interact with your website. Using the platform, you can generate heatmaps to see where users click on your pages, what they ignore, and so on. Further on, it offers session recording that you can use to get even deeper insights into user experience and test out new ideas. Clarity also integrates with such tools as [Google Analytics](https://docs.microsoft.com/en-us/clarity/ga-integration) to help you better analyze and structure the user data.
Using our Clairty integration, you can easily apply the tool to your Softr application and start collecting insights. Let's quickly go over the steps.
## Getting the project ID
To get started, you need to [create a project](https://docs.microsoft.com/en-us/clarity/getting-started#add-a-new-project) in your Clarity dashboard and connect it to your Softr app under **Website URL**. As soon as the project is ready, go to project settings and copy the ID. Below, you can see where the ID is located and how we've added our Softr application to the Clarity project.

_Getting the Clarity project ID_
## Adding the project ID on Softr
Now that you have the Project ID, navigate to your Softr app's **Settings => Integrations => Microsoft Clarity** and add it there.

_Adding Clarity ID on Softr_
As soon as you **Save your settings** and **publish your Softr app**, you're ready to go!
## Testing the integration
If you don't yet have actual users on your Softr app, you can just perform some activity yourself, and within a few hours it will start appearing in your Clarity dashboard. As soon as you start gathering data, you can start monitoring activity heatmaps, watching user session recordings, and so on.

_User session recording on Clarity_
---
# Weglot
Source: https://docs.softr.io/integrations/weglot
With **Weglot**, you can create a multilingual website on Softr. [Here](https://support.weglot.com/article/320-softr-integration-setup), you can find a step-by-step guide that goes through the whole process.
> **Tip**
>
> In order to translate dynamic content ([List](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/list-block/pQhPYuA28VXr5tLLFBcbCU), [Table](/building-blocks/vikC2AWEpQGkZd4jGyoVxo/table-block-/j7rGwu7J7zuU69h3bZ7HFe), and other blocks linked to external [data sources](/4230abecf813402aa2926466c313290a?pvs=25)), please refer to the [dynamic content translation guide](https://support.weglot.com/article/253-how-to-translate-dynamic-content) by Weglot.
---
# API Setup and Endpoints
Source: https://docs.softr.io/softr-api/api-setup-and-endpoints
You can generate an API token for your Softr account to be used when interacting with the API endpoints. Let's first see how you can generate the token, and then we'll review the available endpoints and provide API call examples.
> **Tip**
>
> You need to be **the owner of the application or a workspace collaborator** to be able to make API calls. Thus, [guest collaborators](/workspace-and-billing/jZP6yaeXMiJCuB6HhS4xKd/workspaces-and-applications/kTbEWSYXhBCbtTB4K9dpKs) of the application won’t be able to make calls.
> **Note**
>
> Depending on your needs, you can also consider using a [Call API](/actions/ntEfT9zSJk6aY54G6W5KGU/call-api/i9f1s3w9wib3oRmS4HZ7MX) action.
## Generating an API token
You authenticate API calls with a **Personal Access Token**. To create one:
1. Open your Softr [Dashboard](https://studio.softr.io/dashboard), click on your workspace in the top-left corner, and go to **API tokens**.

2. Click **Create**, give your token a recognizable name, and pick an expiration period.

_Name your token_
3. Define the **scopes** — choose what the token can access and the permissions it should have — then click **Continue**.

_Define scopes_
4. Copy the token and store it somewhere safe — for security reasons it's shown only once.

_Copy your token_
You'll pass this token in the **Softr-Api-Key** header of every request (see the examples below).
That's it. Now you have your API token that you can use when interacting with your Softr apps through the API. Let's proceed to see what endpoints are available.
> **Tip**
>
> Make sure to have your **Softr app published** before making API calls.
## API Endpoints
### **Create User**
This endpoint allows creating a user inside the specified Softr app within your account. Below is an example of an API call.
```javascript
curl --request POST 'https://studio-api.softr.io/v1/api/users' \
--header 'Softr-Api-Key: uYGskr7MqMeRYrjQjsB8uEQ8n' \
--header 'Softr-Domain: yourdomain.com' \
--header 'Content-Type: application/json' \
--data-raw '{
"full_name": "John Richardson",
"email": "johnr@gmail.com",
"password": "12345678",
"generate_magic_link":true
}'
```
Here, you need to replace the value next to **Softr-Api-Key** with the API token you've generated and add your Softr app's domain/subdomain instead of **yourdomain.com**.
Next, you need to provide the **Full Name** of the new user along with an **Email** and **Password** (replace the values next to **full\_name**, **email**, and **password**).
> **Tip**
>
> If you don't specify a password, it will be generated for the user automatically.
Finally, you can set the value of **generate\_magic\_link** to "true" or "false" depending on whether you want to generate a [Magic Link](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/add-or-import-users-manually/g5R1bGnBTFJ3sWLR8Mgdng) for the user or not.
### **Delete User**
Using this endpoint, you can delete a user from the specified Softr app. Bellow is an example of an API call.
```javascript
curl --location --request DELETE 'https://studio-api.softr.io/v1/api/users/user@softr.io' \
-header 'Softr-Api-Key: pYSskw7MqMeRUgjQtsf9uRQ5n' \
-header 'Softr-Domain: yourdomain.com'
```
Just replace **** with the actual email of the user you need to delete as well as provide your API token (the value next to **Softr-Api-Key**) and the domain/subdomain of the Softr app (the value next to **Softr-Domain**) you want to delete the user from. **The rest needs to remain the same as in the example.**
### **Deactivate User**
Using this endpoint, you can deactivate a user in the specified Softr app. Deactivated users cannot log in and don't count toward your plan's user limit, but their record is retained and they can be re-activated later. Below is an example of an API call.
```javascript
curl --location --request POST 'https://studio-api.softr.io/v1/api/users/user@softr.io/deactivate' \
--header 'Softr-Api-Key: pYSskw7MqMeRUgjQtsf9uRQ5n' \
--header 'Softr-Domain: yourdomain.com'
```
Just replace **** with the actual email of the user you need to deactivate as well as provide your API token (the value next to **Softr-Api-Key**) and the domain/subdomain of the Softr app (the value next to **Softr-Domain**) you want to deactivate the user in. **The rest needs to remain the same as in the example.**
### **Activate User**
Using this endpoint, you can re-activate a previously deactivated user in the specified Softr app. Below is an example of an API call.
```javascript
curl --location --request POST 'https://studio-api.softr.io/v1/api/users/user@softr.io/activate' \
--header 'Softr-Api-Key: pYSskw7MqMeRUgjQtsf9uRQ5n' \
--header 'Softr-Domain: yourdomain.com'
```
Just replace **** with the actual email of the user you need to activate as well as provide your API token (the value next to **Softr-Api-Key**) and the domain/subdomain of the Softr app (the value next to **Softr-Domain**) you want to activate the user in. **The rest needs to remain the same as in the example.**
### **Invite User**
Using this endpoint, you can send an invitation email to an existing user of the specified Softr app. Once invited, the user's status changes to **Invited**. Note that the **app must be published** for invitations to be sent. Below is an example of an API call.
```javascript
curl --location --request POST 'https://studio-api.softr.io/v1/api/users/user@softr.io/invite' \
--header 'Softr-Api-Key: pYSskw7MqMeRUgjQtsf9uRQ5n' \
--header 'Softr-Domain: yourdomain.com'
```
Just replace **** with the actual email of the user you need to invite as well as provide your API token (the value next to **Softr-Api-Key**) and the domain/subdomain of the Softr app (the value next to **Softr-Domain**) you want to invite the user in. **The rest needs to remain the same as in the example.**
### **Generate a Magic Link for the User**
Using this endpoint, you cangenerate a [Magic Link](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/add-or-import-users-manually/g5R1bGnBTFJ3sWLR8Mgdng) for the specified user in your Softr app. Bellow is an example of an API call.
```javascript
curl --location --request POST 'https://studio-api.softr.io/v1/api/users/magic-link/generate/user@softr.io' \
--header 'Softr-Api-Key: pYSskw7MqMeRUgjQtsf9uRQ5n' \
--header 'Softr-Domain: yourdomain.com'
```
Just replace **** with the actual email of the user as well as provide your API token (the value next to **Softr-Api-Key**) and the domain/subdomain of your Softr app (the value next to **Softr-Domain**).
### Sync a Single User, Group of Users, or All Users
Use this endpoint to sync a single user, an array of users, or if no email is included, trigger a user sync for all users.
**Single User or Group of Users:**
```javascript
curl --location --request POST 'https://studio-api.softr.io/v1/api/users/sync' \
--header 'Softr-Api-Key: pYSskw7MqMeRUgjQtsf9uRQ5n' \
--header 'Softr-Domain: yourdomain.com'
--data-raw '["email1@example.com", "email2@example.com", "email3@example.com"]'
```
**Sync All Users:**
```javascript
curl --location --request POST 'https://studio-api.softr.io/v1/api/users/sync' \
--header 'Softr-Api-Key: pYSskw7MqMeRUgjQtsf9uRQ5n' \
--header 'Softr-Domain: yourdomain.com'
```
### **Validate an Authentication Token**
Using this endpoint you can validate a user authentication JWT token. This could be used in cases when you use Softr users data (e.g. to show content based on user ID) in external systems outside of Softr and need to authenticate the users with Softr. Here's how you can do that. The following is an example of an API call, where you need to replace **"yourdomain.softr.app"** with your Softr subdomain or custom domain you have connected as well as use the specific token you need to authenticate instead of **your jwt token value**.
```javascript
curl --location --request POST '[https://yourdomain.softr.app/v1/api/users/validate-token](https://yourdomain.softr.app/v1/api/users/validate-token)' \
--header 'Content-Type: application/json' \
--data-raw '{"jwt":"your jwt token value"}'
```
## Use Cases
There are certainly a lot of different use cases for interacting with the Softr API. But if you're working with no-code tools, you can make API calls with such tools as Zapier or Integromat. In subsections to this article, we consider some use cases involving [Zapier](/softr-api/tTFQ5vSAUozj5MsKixMH8C/use-case-adding-users-through-zapier/mhCMmdRcJL2UDsprwzFYuT) and [Make](/softr-api/tTFQ5vSAUozj5MsKixMH8C/use-case-adding-users-through-make-formerly-integromat/vFH1YQTF7At7FwCYSmJKYz) to take you through the setup process.
---
# Use Case: Adding Users through Zapier
Source: https://docs.softr.io/softr-api/use-case-adding-users-through-zapier
**Option 1: Using Zapier's Softr app**
Let's see how you can use the API to add users via Zapier. In this example, we are going to sync a Softr App with Google Sheets using Zapier's Softr app (this is solely for demonstration purposes, and we don't recommend storing user data on Google Sheets or similar sources). Let's proceed.
1. **Configuring the Action**
In the Action search bar enter "softr" and select the Softr action.

_Locating the Softr app_
Next, we are going to select the **Action Event**. In our case, we need to choose "**Create a user**."

_Choosing the Create User action event_
Further on, we need to link our Softr account (by entering the API key, we generated previously), then add the Application domain, map the **Email**, **Name**, and **Password** fields. We can also set to generate a [Magic Link](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/add-or-import-users-manually/g5R1bGnBTFJ3sWLR8Mgdng), but we are going to set it to **False** in our case. See below.

_Connecting account and domain and mapping fields_
That's it. Now, as soon as you activate your Zap, all the new users added to your spreadsheet, will be added to your selected Softr app as well.
**Option 2: Using custom webhook**
In this use case, we are going to add users to a Softr app using Zapier's **Custom Webhook**
instead of the Zapier Softr app. So, the first step (**Setting the Trigger**) is going to be similar to that of **Option 1**.

_Users data_
1. **Setting the Trigger**
First of all, we're going to create a spreadsheets with **Name**, **Email**, and **Password** columns to store user data.

_Users sheets_
Further on, we'll create a Zap on Zapier and set the **trigger** for each new row creation in our Google sheet. See below.

_Setting the trigger_
Next, we'll test the trigger and proceed to configuring the **Action** to define what's going to happen when the initial event is triggered.
2. **Configuring the Action**
In the Action search bar enter "webhook" and select **Webhooks by Zapier** (please note that this is a **paid** feature).

_Selecting “Webhooks by Zapier”_
In the following screen, we need to select **POST** as the **Action event** since we need to create a user using the POST request as described above.
In the next screen, we need to fill in all the necessary details based on the [create user endpoint](/softr-api/tTFQ5vSAUozj5MsKixMH8C/api-setup-and-endpoints/j1PrTZxt7pv3iZCnZ5Fp19). Thus, we need to set the **URL** to "", set the **Payload Type** to "json", and map the **data** as shown below.

_URL, Payload Type, and Data Mapping_
The following configs can be left intact, and we just need to add the **headers** using our **API key**
and **domain** as shown below.

_Headers configured_
3. **Testing the Action**
That's it. Now, we just need to hit Continue and test the action. As you can see below, as soon as we do the test, the user we had added earlier on Google Sheets is added to our Softr app. So, as soon as you make sure it's working correctly, you can turn on the Zap to start the automation.

_Testing the action_
## **Deleting a User**
The [delete request](/softr-api/tTFQ5vSAUozj5MsKixMH8C/api-setup-and-endpoints/j1PrTZxt7pv3iZCnZ5Fp19) can be implemented in a similar way through a custom webhook.
## Zapier templates for Softr
Zapier offers a number of ready-made templates for Softr (the list is available [here](https://zapier.com/apps/softr/integrations)) that let you select from a variety of use cases and get started easily. So, let’s see what kind of templates are available

_Zapier templates for Softr_
### Database/spreadsheet templates
Most of the templates involve spreadsheet or database tools such as Google Sheets, Airtable, or Coda. Those work the following way: every time a new record/row is added to the database, a new user is automatically created on Softr based on that record/row.
### Form templates
This category involves form builder platforms such as Google Form, Jotform, and TypeForm. The templates create a new Softr user for each new form submission. Let’s say you’ve built an online community with Softr, and there are several community moderators. Using one of these templates, you can provide a way for your moderators to add new users directly from the app user interface instead of giving them access to your Softr app’s [studio](https://studio.softr.io).
### Stripe template
This template connects [Stripe](/integrations/etS18kJqm1fuD58KCsjC3z/stripe-checkout/iBomMEucRZtM2y6HuutYVC) to your Softr app, creating a new Softr user for each new Stripe customer you get. Let’s say you have an online shop that processes payments using Stripe, and you’ve also created a Softr application for your shop customers to interact with one another and also get access to perks. Using this template, you can automatically sync all your customers along with their details with your Softr-built app.
### Webhook template
This template just connects Softr with a [Zapier webhook](https://zapier.com/features/webhooks), which lets you receive data from any service even if it’s not available in Zapier.
---
# Use Case: Adding Users through Make (formerly Integromat
Source: https://docs.softr.io/softr-api/use-case-adding-users-through-make-formerly-integromat
In this use case, we are going to use the API to add users to a Softr app via Make. We are going to add users on Airtable and send them to Softr. Let's proceed.
**Option 1: Make's Softr module**
1. **Setting a Trigger**
First of all, we're going to create a table on Airtable with **Name**, **Email**, **Password**, **Magic Link, Created Date/Time** (needed for watching record creation in Make) columns to store user data.

_Table setup on Airtable_
Then, we'll go to Make dashboard, create a new scenario, and add a trigger that watches for new records on our selected table. See below.

_Creating the trigger_
Now, we need to set up an **Action** to add the users received from Airtable. There are two options for this:
- **Make's Softr module;**
- **Custom HTTPrequest.**
Let's consider each option separately.
2. **Configuring the Action**
Let's add a new module to the scenario, search for "Softr," and select it.

_Locating the Softr module_
Then, we are going to choose the **Create a User** option.

_Choosing the Action_
Next, we need to establish a connection with our Softr account and app, inputing the [Softr API key](/softr-api/tTFQ5vSAUozj5MsKixMH8C/api-setup-and-endpoints/j1PrTZxt7pv3iZCnZ5Fp19) and the domain of the app we want to add users to.

_Adding a Softr connection_
Lastly, we need to map the user fields from our table as shown below.

_Mapping the user fields_
> **Tip**
>
> As you can see, we haven't mapped the **Magiclink** field from the table but have just set the value to **Yes** to generate one automatically. We can sync it back to a [Airtable](/f001252ed01e495d8c0f8e2588f06107) if we [connect it to Softr](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/syncing-users-with-a-data-source/hshRGygHr4T33EnaLntGf9), which we'll discuss in **Step 3**.
That's it. Now, we just need to save the module and the scenario is ready. Let's test it to make sure everything is working correctly.
3. **Testing the Scenario**
Let's add a new user to our table and check if it's sent to our Softr app successfully.
> **Tip**
>
> This is optional, but we are also going to [connect our Softr users base](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/syncing-users-with-a-data-source/hshRGygHr4T33EnaLntGf9) to the same Airtable base and table at the beginning to sync user data **from** **Softr to Airtable** as well. This way, the magic link that's been generated when fetching the user **from Airtable to Softr** will be stored in Softr and eventually **synced back to Airtable**.

_Testing the scenario_
**Option 2: Using a Custom HTTP Request**
1. **Setting a Trigger**
First of all, we're going to create a table on Airtable with **Name**, **Email**, **Password**, **Magic Link, Created Date/Time** (needed for watching record creation in Make) columns to store user data.

_Table setup on Airtable_
Then, we'll go to Make dashboard, create a new scenario, and add a trigger that watches for new records on our selected table. See below.

_Creating the trigger_
Now, we need to set up an **Action** to add the users received from Airtable. There are two options for this:
- **Make's Softr module;**
- **Custom HTTPrequest.**
Let's consider each option separately.
2. **Configuring the Action**
In this case, we need to create a new module, search for **HTTP**, select it, and choose the **Make a request** action.

_Selecting the action_
Now, let's start configuring the module based on our [endpoint](/softr-api/tTFQ5vSAUozj5MsKixMH8C/api-setup-and-endpoints/j1PrTZxt7pv3iZCnZ5Fp19). First we need to add our **URL**, then select the **method** (POST), and finally add the required **headers**. We don't need to add the **Content-Type** header, as it's going to be added in the next step. Below, you can see what it should look like.

_Configuring URL, Method, and Headers_
Further on, we need to set the **Body Type** to **Raw** and the **Content Type to JSON**. Lastly, we are going to fill in the **Request Content** using the format provided above. Please, note that the **Parse response** option should be set to **Yes**.

_Configuring Body and Content types and adding Request content_
3. **Testing the Scenario**
So, we're almost there. Let's just add a new record in our table and run the scenario to test it. As, you can see below, the user is successfully added to our Softr app.
> **Tip**
>
> This is optional, but we are also going to [connect our Softr users base](/add-and-manage-users/pxnkp9H3qyEVMF6XUceqnj/syncing-users-with-a-data-source/hshRGygHr4T33EnaLntGf9) to the same [Airtable](/f001252ed01e495d8c0f8e2588f06107) base and table at the beginning to sync user data **from** **Softr to Airtable** as well. This way, the magiclink that's been generated when fetching the user **from Airtable to Softr** will be stored in Softr and eventually **synced back to Airtable**.

_Testing the scenario_
## Deleting a User
The [delete request](/softr-api/tTFQ5vSAUozj5MsKixMH8C/api-setup-and-endpoints/j1PrTZxt7pv3iZCnZ5Fp19) can be implemented in a similar way through an HTTP (Make a request) module.
---
# Softr Database API
Source: https://docs.softr.io/softr-api/softr-database-api
The Softr Database API lets you integrate your Softr data with external systems. The API follows REST semantics, uses JSON to encode objects, and requires all requests to be made over HTTPS.
Download the [OpenAPI specification](/openapi.yaml) to import into tools like Postman or use for code generation.
## Video Introduction
## Data Model
The API is organized around four core resources:
- **Database** — A top-level container that belongs to a workspace. Each database holds one or more tables.
- **Table** — A structured collection of records, similar to a spreadsheet or database table. Each table has a set of fields and one or more views.
- **Field** — A column definition on a table. Fields have a type (e.g. `SINGLE_LINE_TEXT`, `NUMBER`, `SELECT`) and optional configuration. Some fields are read-only (computed or system-managed).
- **Record** — A single row of data in a table. Record values are stored in a `fields` object, keyed by field ID. Responses can use field names instead (`?fieldNames=true`); requests always use field IDs.
Every resource is identified by its ID.
## Authentication
All requests require a **Personal Access Token (PAT)** passed in the `Softr-Api-Key` header:
```bash
curl -X GET 'https://tables-api.softr.io/api/v1/databases' \
-H 'Softr-Api-Key: '
```
Tokens are scoped to one or more workspaces — you can only access databases within your authorized workspaces. See [Authorisation](/softr-api/softr-database-api/authorisation) for how to generate a token.
## Quick Start
**1. List your databases:**
```bash
curl -X GET 'https://tables-api.softr.io/api/v1/databases' \
-H 'Softr-Api-Key: '
```
**2. Get records from a table:**
```bash
curl -X GET 'https://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}/records?limit=10&fieldNames=true' \
-H 'Softr-Api-Key: '
```
**3. Create a record** (the keys are field IDs; [Get Single Table](/softr-api/softr-database-api/tables/get-single-table) lists a table's fields with their IDs):
```bash
curl -X POST 'https://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}/records' \
-H 'Softr-Api-Key: ' \
-H 'Content-Type: application/json' \
-d '{
"fields": {
"": "Jane Doe",
"": "jane@example.com"
}
}'
```
## Response Format
### Success (single item)
```json
{
"data": { ... },
"metadata": null
}
```
### Success (paginated list)
```json
{
"data": [ ... ],
"metadata": {
"offset": 0,
"limit": 20,
"total": 100
}
}
```
### Error
```json
{
"message": "Human-readable error message",
"errorCode": "MACHINE_READABLE_CODE",
"details": {
"fieldId": "Additional context",
"traceId": "abc-123"
}
}
```
## Error Codes
| Code | HTTP Status | Description |
| ---------------------- | ----------- | ------------------------------------------------------- |
| `BAD_REQUEST` | 400 | Invalid request format or data |
| `VALIDATION_ERROR` | 400 | Field validation failed |
| `UNKNOWN_FIELD` | 400 | Unrecognized field in request |
| `UNAUTHORIZED` | 401 | Missing or invalid token |
| `QUOTA_EXCEEDED` | 402 | Plan quota limit reached |
| `FORBIDDEN` | 403 | Insufficient permissions |
| `RESOURCE_NOT_FOUND` | 404 | Resource does not exist |
| `CONSTRAINT_VIOLATION` | 409 | Data constraint violation (e.g. duplicate unique value) |
| `PAYLOAD_TOO_LARGE` | 413 | Request body exceeds 64 MB |
| `TOO_MANY_REQUESTS` | 429 | Rate limit exceeded |
| `SERVICE_UNAVAILABLE` | 503 | Service temporarily unavailable |
## Pagination
All list endpoints support offset-based pagination:
| Parameter | Default | Max | Description |
| --------- | ------- | ----- | -------------------------- |
| `offset` | `0` | — | Number of records to skip |
| `limit` | `20` | `200` | Number of records per page |
The response `metadata` includes a `total` count. To iterate through all records:
```
GET .../records?offset=0&limit=100 → records 1–100
GET .../records?offset=100&limit=100 → records 101–200
GET .../records?offset=200&limit=100 → records 201–300
```
Stop when `offset >= metadata.total`.
## Using Field Names
By default, the `fields` object in record responses uses **field IDs** as keys. Pass `?fieldNames=true` on any record endpoint to get **human-readable field names** in the response instead:
```bash
# With field IDs (default)
GET .../records
→ { "fields": { "fld_abc123": "Jane Doe" } }
# With field names
GET .../records?fieldNames=true
→ { "fields": { "Full Name": "Jane Doe" } }
```
`fieldNames` changes the response only. The `fields` of a create or update request and the field references of a
search (`leftSide`, `sortingField`) always take field IDs; a field name there fails with `Unknown field`.
## Quick Links
- [Authorisation](/softr-api/softr-database-api/authorisation)
- [Rate Limiting](/softr-api/softr-database-api/rate-limiting)
- [Databases](/softr-api/softr-database-api/databases/get-databases)
- [Tables](/softr-api/softr-database-api/tables/get-tables)
- [Table Fields](/softr-api/softr-database-api/table-fields/get-table-field)
- [Records](/softr-api/softr-database-api/records/get-records)
- [Search & Filtering](/softr-api/softr-database-api/records/search-records)
---
# Authorisation
Source: https://docs.softr.io/softr-api/softr-database-api/authorisation
All API requests must be authenticated and made over HTTPS.
## Base URL
```
https://tables-api.softr.io/api/v1
```
## Authentication
Pass your Personal Access Token (PAT) in the `Softr-Api-Key` header:
```bash
curl -X GET 'https://tables-api.softr.io/api/v1/databases' \
-H 'Softr-Api-Key: '
```
To generate a token, go to [API Setup and Endpoints](/softr-api/api-setup-and-endpoints).
## Token Scoping
- Tokens are scoped to one or more **workspaces**. You can only access databases within your authorized workspaces.
- The token inherits the access rights of the user who created it.
- We currently support Personal Access Tokens only. OAuth access tokens may be supported in the future.
---
# Rate Limiting
Source: https://docs.softr.io/softr-api/softr-database-api/rate-limiting
All API calls are subject to rate limiting, enforced per token.
| Operation Type | Limit |
| --------------------------------------------- | ------------------ |
| **Reads** (`GET`, `POST /search`) | 40 requests/second |
| **Writes** (`POST`, `PUT`, `PATCH`, `DELETE`) | 30 requests/second |
When the limit is exceeded, the API returns a `429 Too Many Requests` HTTP status code. Back off and retry after a short delay.
---
# Get Databases
Source: https://docs.softr.io/softr-api/softr-database-api/databases/get-databases
## Endpoint
`GET https://tables-api.softr.io/api/v1/databases`
Retrieve a list of all databases accessible to the authenticated user.
## Authorizations
- `Softr-Api-Key` (API key, header, required)
## Responses
### 200: A list of databases.
- `data` (object[])
- `data.id` (string)
- `data.name` (string)
- `data.description` (string | null)
- `data.workspaceId` (string)
- `data.tablesCount` (integer): Number of tables in this database.
- `data.createdAt` (string)
- `data.updatedAt` (string)
```json
{
"data": [
{
"id": "",
"name": "",
"description": "",
"workspaceId": "",
"tablesCount": 123,
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
]
}
```
### 429: Rate limit exceeded.
- `message` (string): A human-readable error message.
- `errorCode` (string): A machine-readable error code (e.g. BAD_REQUEST, VALIDATION_ERROR, RESOURCE_NOT_FOUND).
- `details` (Record): Additional context about the error (e.g. fieldId, traceId).
```json
{
"message": "",
"errorCode": "",
"details": {}
}
```
## Request example
```bash
curl --request GET \
--url 'https://tables-api.softr.io/api/v1/databases' \
--header 'Softr-Api-Key: '
```
---
# Get Single Database
Source: https://docs.softr.io/softr-api/softr-database-api/databases/get-single-database
## Endpoint
`GET https://tables-api.softr.io/api/v1/databases/{databaseId}`
Retrieve details of a specific database by its ID.
## Authorizations
- `Softr-Api-Key` (API key, header, required)
## Path parameters
- `databaseId` (string, required)
## Responses
### 200: Database details.
- `data` (object)
- `data.id` (string)
- `data.name` (string)
- `data.description` (string | null)
- `data.workspaceId` (string)
- `data.tablesCount` (integer): Number of tables in this database.
- `data.createdAt` (string)
- `data.updatedAt` (string)
```json
{
"data": {
"id": "",
"name": "",
"description": "",
"workspaceId": "",
"tablesCount": 123,
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
}
```
### 429: Rate limit exceeded.
No response body.
## Request example
```bash
curl --request GET \
--url 'https://tables-api.softr.io/api/v1/databases/' \
--header 'Softr-Api-Key: '
```
---
# Create a Database
Source: https://docs.softr.io/softr-api/softr-database-api/databases/create-a-database
## Endpoint
`POST https://tables-api.softr.io/api/v1/databases`
Create a new database in the specified workspace.
## Authorizations
- `Softr-Api-Key` (API key, header, required)
## Body (application/json)
- `workspaceId` (string, required)
- `name` (string, required)
- `description` (string)
## Responses
### 200: The newly created database.
- `data` (object)
- `data.id` (string)
- `data.name` (string)
- `data.description` (string | null)
- `data.workspaceId` (string)
- `data.tablesCount` (integer): Number of tables in this database.
- `data.createdAt` (string)
- `data.updatedAt` (string)
```json
{
"data": {
"id": "",
"name": "",
"description": "",
"workspaceId": "",
"tablesCount": 123,
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
}
```
### 429: Rate limit exceeded.
No response body.
## Request example
```bash
curl --request POST \
--url 'https://tables-api.softr.io/api/v1/databases' \
--header 'Softr-Api-Key: ' \
--header 'Content-Type: application/json' \
--data '{
"workspaceId": "",
"name": ""
}'
```
---
# Update Database
Source: https://docs.softr.io/softr-api/softr-database-api/databases/update-database
## Endpoint
`PUT https://tables-api.softr.io/api/v1/databases/{databaseId}`
Update the details of an existing database.
## Authorizations
- `Softr-Api-Key` (API key, header, required)
## Path parameters
- `databaseId` (string, required)
## Body (application/json)
- `name` (string)
- `description` (string)
## Responses
### 200: The updated database.
- `data` (object)
- `data.id` (string)
- `data.name` (string)
- `data.description` (string | null)
- `data.workspaceId` (string)
- `data.tablesCount` (integer): Number of tables in this database.
- `data.createdAt` (string)
- `data.updatedAt` (string)
```json
{
"data": {
"id": "",
"name": "",
"description": "",
"workspaceId": "",
"tablesCount": 123,
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
}
```
### 429: Rate limit exceeded.
No response body.
## Request example
```bash
curl --request PUT \
--url 'https://tables-api.softr.io/api/v1/databases/' \
--header 'Softr-Api-Key: ' \
--header 'Content-Type: application/json' \
--data '{
"name": "",
"description": ""
}'
```
---
# Delete Database
Source: https://docs.softr.io/softr-api/softr-database-api/databases/delete-database
## Endpoint
`DELETE https://tables-api.softr.io/api/v1/databases/{databaseId}`
Delete a specific database by its ID. It can only be deleted if it is empty, unless the 'force' parameter is used.
## Authorizations
- `Softr-Api-Key` (API key, header, required)
## Path parameters
- `databaseId` (string, required)
## Query parameters
- `force` (boolean, default: false)
## Responses
### 204: Database deleted successfully.
No response body.
### 400: Bad Request - Database is not empty and force=true was not provided.
No response body.
### 429: Rate limit exceeded.
No response body.
## Request example
```bash
curl --request DELETE \
--url 'https://tables-api.softr.io/api/v1/databases/' \
--header 'Softr-Api-Key: '
```
---
# Get Tables
Source: https://docs.softr.io/softr-api/softr-database-api/tables/get-tables
## Endpoint
`GET https://tables-api.softr.io/api/v1/databases/{databaseId}/tables`
Retrieve a list of all tables in the specified database.
## Authorizations
- `Softr-Api-Key` (API key, header, required)
## Path parameters
- `databaseId` (string, required)
## Responses
### 200: A list of tables.
- `data` (object[])
- `data.id` (string)
- `data.name` (string)
- `data.description` (string | null)
- `data.primaryFieldId` (string)
- `data.defaultViewId` (string)
- `data.fields` (object[])
- `data.fields.id` (string)
- `data.fields.name` (string)
- `data.fields.description` (string | null): Optional description of the field.
- `data.fields.type` (enum): The type of the field. One of: `SINGLE_LINE_TEXT`, `CHECKBOX`, `CURRENCY`, `DATE`, `DATETIME`, `DURATION`, `EMAIL`, `SELECT`, `NUMBER`, `ATTACHMENT`, `RATING`, `LINKED_RECORD`, `LONG_TEXT`, `URL`, `PERCENT`, `PHONE`, `LOOKUP`, `ROLLUP`, `FORMULA`, `CREATED_AT`, `UPDATED_AT`, `CREATED_BY`, `UPDATED_BY`, `AUTONUMBER`, `RECORD_ID`, `USER`.
- `data.fields.options` (Record): Configuration options for the field, specific to its type. See the official documentation for the structure of each type.
- `data.fields.allowMultipleEntries` (boolean)
- `data.fields.readonly` (boolean)
- `data.fields.required` (boolean)
- `data.fields.locked` (boolean)
- `data.fields.defaultValue` (string | null)
- `data.fields.aiOptions` (object | null): AI-powered auto-fill configuration. Null if not configured.
- `data.fields.aiOptions.aiFillable` (boolean)
- `data.fields.aiOptions.aiOnly` (boolean)
- `data.fields.aiOptions.allowWebSearch` (boolean)
- `data.fields.aiOptions.aiModel` (string)
- `data.fields.aiOptions.prompt` (string)
- `data.fields.aiOptions.canBeTriggeredManually` (boolean)
- `data.fields.aiOptions.runWhenRecordIsCreated` (boolean)
- `data.fields.aiOptions.runWhenRecordIsUpdated` (boolean)
- `data.fields.createdAt` (string)
- `data.fields.updatedAt` (string)
- `data.createdAt` (string)
- `data.updatedAt` (string)
```json
{
"data": [
{
"id": "",
"name": "",
"description": "",
"primaryFieldId": "",
"defaultViewId": "",
"fields": [
{
"id": "",
"name": "",
"description": "",
"type": "SINGLE_LINE_TEXT",
"options": {},
"allowMultipleEntries": true,
"readonly": true,
"required": true,
"locked": true,
"defaultValue": "",
"aiOptions": {
"aiFillable": true,
"aiOnly": true,
"allowWebSearch": true,
"aiModel": "",
"prompt": "",
"canBeTriggeredManually": true,
"runWhenRecordIsCreated": true,
"runWhenRecordIsUpdated": true
},
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
],
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
]
}
```
### 429: Rate limit exceeded.
No response body.
## Request example
```bash
curl --request GET \
--url 'https://tables-api.softr.io/api/v1/databases//tables' \
--header 'Softr-Api-Key: '
```
---
# Get Single Table
Source: https://docs.softr.io/softr-api/softr-database-api/tables/get-single-table
## Endpoint
`GET https://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}`
Retrieve details of a specific table by its ID.
## Authorizations
- `Softr-Api-Key` (API key, header, required)
## Path parameters
- `databaseId` (string, required)
- `tableId` (string, required)
## Responses
### 200: Table details.
- `data` (object)
- `data.id` (string)
- `data.name` (string)
- `data.description` (string | null)
- `data.primaryFieldId` (string)
- `data.defaultViewId` (string)
- `data.fields` (object[])
- `data.fields.id` (string)
- `data.fields.name` (string)
- `data.fields.description` (string | null): Optional description of the field.
- `data.fields.type` (enum): The type of the field. One of: `SINGLE_LINE_TEXT`, `CHECKBOX`, `CURRENCY`, `DATE`, `DATETIME`, `DURATION`, `EMAIL`, `SELECT`, `NUMBER`, `ATTACHMENT`, `RATING`, `LINKED_RECORD`, `LONG_TEXT`, `URL`, `PERCENT`, `PHONE`, `LOOKUP`, `ROLLUP`, `FORMULA`, `CREATED_AT`, `UPDATED_AT`, `CREATED_BY`, `UPDATED_BY`, `AUTONUMBER`, `RECORD_ID`, `USER`.
- `data.fields.options` (Record): Configuration options for the field, specific to its type. See the official documentation for the structure of each type.
- `data.fields.allowMultipleEntries` (boolean)
- `data.fields.readonly` (boolean)
- `data.fields.required` (boolean)
- `data.fields.locked` (boolean)
- `data.fields.defaultValue` (string | null)
- `data.fields.aiOptions` (object | null): AI-powered auto-fill configuration. Null if not configured.
- `data.fields.aiOptions.aiFillable` (boolean)
- `data.fields.aiOptions.aiOnly` (boolean)
- `data.fields.aiOptions.allowWebSearch` (boolean)
- `data.fields.aiOptions.aiModel` (string)
- `data.fields.aiOptions.prompt` (string)
- `data.fields.aiOptions.canBeTriggeredManually` (boolean)
- `data.fields.aiOptions.runWhenRecordIsCreated` (boolean)
- `data.fields.aiOptions.runWhenRecordIsUpdated` (boolean)
- `data.fields.createdAt` (string)
- `data.fields.updatedAt` (string)
- `data.createdAt` (string)
- `data.updatedAt` (string)
```json
{
"data": {
"id": "",
"name": "",
"description": "",
"primaryFieldId": "",
"defaultViewId": "",
"fields": [
{
"id": "",
"name": "",
"description": "",
"type": "SINGLE_LINE_TEXT",
"options": {},
"allowMultipleEntries": true,
"readonly": true,
"required": true,
"locked": true,
"defaultValue": "",
"aiOptions": {
"aiFillable": true,
"aiOnly": true,
"allowWebSearch": true,
"aiModel": "",
"prompt": "",
"canBeTriggeredManually": true,
"runWhenRecordIsCreated": true,
"runWhenRecordIsUpdated": true
},
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
],
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
}
```
### 429: Rate limit exceeded.
No response body.
## Request example
```bash
curl --request GET \
--url 'https://tables-api.softr.io/api/v1/databases//tables/' \
--header 'Softr-Api-Key: '
```
---
# Get Table Views
Source: https://docs.softr.io/softr-api/softr-database-api/tables/get-table-views
## Endpoint
`GET https://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}/views`
Retrieve a list of views for a specific table.
## Authorizations
- `Softr-Api-Key` (API key, header, required)
## Path parameters
- `databaseId` (string, required)
- `tableId` (string, required)
## Responses
### 200: A list of table views.
- `data` (object[])
- `data.id` (string)
- `data.tableId` (string)
- `data.name` (string)
- `data.description` (string | null)
- `data.createdAt` (string)
- `data.updatedAt` (string)
```json
{
"data": [
{
"id": "",
"tableId": "",
"name": "",
"description": "",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
]
}
```
### 429: Rate limit exceeded.
No response body.
## Request example
```bash
curl --request GET \
--url 'https://tables-api.softr.io/api/v1/databases//tables//views' \
--header 'Softr-Api-Key: '
```
---
# Create Table
Source: https://docs.softr.io/softr-api/softr-database-api/tables/create-table
## Endpoint
`POST https://tables-api.softr.io/api/v1/databases/{databaseId}/tables`
Create a new table in the specified database.
## Authorizations
- `Softr-Api-Key` (API key, header, required)
## Path parameters
- `databaseId` (string, required)
## Body (application/json)
- `name` (string)
- `description` (string)
- `primaryFieldName` (string)
- `fields` (object[])
- `fields.name` (string)
- `fields.type` (string)
- `fields.options` (Record)
## Responses
### 200: The newly created table.
- `data` (object)
- `data.id` (string)
- `data.name` (string)
- `data.description` (string | null)
- `data.primaryFieldId` (string)
- `data.defaultViewId` (string)
- `data.fields` (object[])
- `data.fields.id` (string)
- `data.fields.name` (string)
- `data.fields.description` (string | null): Optional description of the field.
- `data.fields.type` (enum): The type of the field. One of: `SINGLE_LINE_TEXT`, `CHECKBOX`, `CURRENCY`, `DATE`, `DATETIME`, `DURATION`, `EMAIL`, `SELECT`, `NUMBER`, `ATTACHMENT`, `RATING`, `LINKED_RECORD`, `LONG_TEXT`, `URL`, `PERCENT`, `PHONE`, `LOOKUP`, `ROLLUP`, `FORMULA`, `CREATED_AT`, `UPDATED_AT`, `CREATED_BY`, `UPDATED_BY`, `AUTONUMBER`, `RECORD_ID`, `USER`.
- `data.fields.options` (Record): Configuration options for the field, specific to its type. See the official documentation for the structure of each type.
- `data.fields.allowMultipleEntries` (boolean)
- `data.fields.readonly` (boolean)
- `data.fields.required` (boolean)
- `data.fields.locked` (boolean)
- `data.fields.defaultValue` (string | null)
- `data.fields.aiOptions` (object | null): AI-powered auto-fill configuration. Null if not configured.
- `data.fields.aiOptions.aiFillable` (boolean)
- `data.fields.aiOptions.aiOnly` (boolean)
- `data.fields.aiOptions.allowWebSearch` (boolean)
- `data.fields.aiOptions.aiModel` (string)
- `data.fields.aiOptions.prompt` (string)
- `data.fields.aiOptions.canBeTriggeredManually` (boolean)
- `data.fields.aiOptions.runWhenRecordIsCreated` (boolean)
- `data.fields.aiOptions.runWhenRecordIsUpdated` (boolean)
- `data.fields.createdAt` (string)
- `data.fields.updatedAt` (string)
- `data.createdAt` (string)
- `data.updatedAt` (string)
```json
{
"data": {
"id": "",
"name": "",
"description": "",
"primaryFieldId": "",
"defaultViewId": "",
"fields": [
{
"id": "",
"name": "",
"description": "",
"type": "SINGLE_LINE_TEXT",
"options": {},
"allowMultipleEntries": true,
"readonly": true,
"required": true,
"locked": true,
"defaultValue": "",
"aiOptions": {
"aiFillable": true,
"aiOnly": true,
"allowWebSearch": true,
"aiModel": "",
"prompt": "",
"canBeTriggeredManually": true,
"runWhenRecordIsCreated": true,
"runWhenRecordIsUpdated": true
},
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
],
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
}
```
### 429: Rate limit exceeded.
No response body.
## Request example
```bash
curl --request POST \
--url 'https://tables-api.softr.io/api/v1/databases//tables' \
--header 'Softr-Api-Key: ' \
--header 'Content-Type: application/json' \
--data '{
"name": "",
"description": "",
"primaryFieldName": "",
"fields": [
{
"name": "",
"type": "",
"options": {}
}
]
}'
```
---
# Update Table
Source: https://docs.softr.io/softr-api/softr-database-api/tables/update-table
## Endpoint
`PUT https://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}`
Update a table's name and/or description. To modify fields, use the field-specific endpoints.
## Authorizations
- `Softr-Api-Key` (API key, header, required)
## Path parameters
- `databaseId` (string, required)
- `tableId` (string, required)
## Body (application/json)
- `name` (string)
- `description` (string)
## Responses
### 200: The updated table.
- `data` (object)
- `data.id` (string)
- `data.name` (string)
- `data.description` (string | null)
- `data.primaryFieldId` (string)
- `data.defaultViewId` (string)
- `data.fields` (object[])
- `data.fields.id` (string)
- `data.fields.name` (string)
- `data.fields.description` (string | null): Optional description of the field.
- `data.fields.type` (enum): The type of the field. One of: `SINGLE_LINE_TEXT`, `CHECKBOX`, `CURRENCY`, `DATE`, `DATETIME`, `DURATION`, `EMAIL`, `SELECT`, `NUMBER`, `ATTACHMENT`, `RATING`, `LINKED_RECORD`, `LONG_TEXT`, `URL`, `PERCENT`, `PHONE`, `LOOKUP`, `ROLLUP`, `FORMULA`, `CREATED_AT`, `UPDATED_AT`, `CREATED_BY`, `UPDATED_BY`, `AUTONUMBER`, `RECORD_ID`, `USER`.
- `data.fields.options` (Record): Configuration options for the field, specific to its type. See the official documentation for the structure of each type.
- `data.fields.allowMultipleEntries` (boolean)
- `data.fields.readonly` (boolean)
- `data.fields.required` (boolean)
- `data.fields.locked` (boolean)
- `data.fields.defaultValue` (string | null)
- `data.fields.aiOptions` (object | null): AI-powered auto-fill configuration. Null if not configured.
- `data.fields.aiOptions.aiFillable` (boolean)
- `data.fields.aiOptions.aiOnly` (boolean)
- `data.fields.aiOptions.allowWebSearch` (boolean)
- `data.fields.aiOptions.aiModel` (string)
- `data.fields.aiOptions.prompt` (string)
- `data.fields.aiOptions.canBeTriggeredManually` (boolean)
- `data.fields.aiOptions.runWhenRecordIsCreated` (boolean)
- `data.fields.aiOptions.runWhenRecordIsUpdated` (boolean)
- `data.fields.createdAt` (string)
- `data.fields.updatedAt` (string)
- `data.createdAt` (string)
- `data.updatedAt` (string)
```json
{
"data": {
"id": "",
"name": "",
"description": "",
"primaryFieldId": "",
"defaultViewId": "",
"fields": [
{
"id": "",
"name": "",
"description": "",
"type": "SINGLE_LINE_TEXT",
"options": {},
"allowMultipleEntries": true,
"readonly": true,
"required": true,
"locked": true,
"defaultValue": "",
"aiOptions": {
"aiFillable": true,
"aiOnly": true,
"allowWebSearch": true,
"aiModel": "",
"prompt": "",
"canBeTriggeredManually": true,
"runWhenRecordIsCreated": true,
"runWhenRecordIsUpdated": true
},
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
],
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
}
```
### 429: Rate limit exceeded.
No response body.
## Request example
```bash
curl --request PUT \
--url 'https://tables-api.softr.io/api/v1/databases//tables/' \
--header 'Softr-Api-Key: ' \
--header 'Content-Type: application/json' \
--data '{
"name": "",
"description": ""
}'
```
---
# Delete Table
Source: https://docs.softr.io/softr-api/softr-database-api/tables/delete-table
## Endpoint
`DELETE https://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}`
Delete a specific table by its ID. It can only be deleted if it is empty, unless the 'force' parameter is used.
## Authorizations
- `Softr-Api-Key` (API key, header, required)
## Path parameters
- `databaseId` (string, required)
- `tableId` (string, required)
## Query parameters
- `force` (boolean, default: false)
## Responses
### 204: Table deleted successfully.
No response body.
### 400: Bad Request - Table is not empty and force=true was not provided.
No response body.
### 429: Rate limit exceeded.
No response body.
## Request example
```bash
curl --request DELETE \
--url 'https://tables-api.softr.io/api/v1/databases//tables/' \
--header 'Softr-Api-Key: '
```
---
# Get Table Field
Source: https://docs.softr.io/softr-api/softr-database-api/table-fields/get-table-field
## Endpoint
`GET https://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}/fields/{fieldId}`
Retrieve details of a specific field.
## Authorizations
- `Softr-Api-Key` (API key, header, required)
## Path parameters
- `databaseId` (string, required)
- `tableId` (string, required)
- `fieldId` (string, required)
## Responses
### 200: Field details.
- `data` (object)
- `data.id` (string)
- `data.name` (string)
- `data.description` (string | null): Optional description of the field.
- `data.type` (enum): The type of the field. One of: `SINGLE_LINE_TEXT`, `CHECKBOX`, `CURRENCY`, `DATE`, `DATETIME`, `DURATION`, `EMAIL`, `SELECT`, `NUMBER`, `ATTACHMENT`, `RATING`, `LINKED_RECORD`, `LONG_TEXT`, `URL`, `PERCENT`, `PHONE`, `LOOKUP`, `ROLLUP`, `FORMULA`, `CREATED_AT`, `UPDATED_AT`, `CREATED_BY`, `UPDATED_BY`, `AUTONUMBER`, `RECORD_ID`, `USER`.
- `data.options` (Record): Configuration options for the field, specific to its type. See the official documentation for the structure of each type.
- `data.allowMultipleEntries` (boolean)
- `data.readonly` (boolean)
- `data.required` (boolean)
- `data.locked` (boolean)
- `data.defaultValue` (string | null)
- `data.aiOptions` (object | null): AI-powered auto-fill configuration. Null if not configured.
- `data.aiOptions.aiFillable` (boolean)
- `data.aiOptions.aiOnly` (boolean)
- `data.aiOptions.allowWebSearch` (boolean)
- `data.aiOptions.aiModel` (string)
- `data.aiOptions.prompt` (string)
- `data.aiOptions.canBeTriggeredManually` (boolean)
- `data.aiOptions.runWhenRecordIsCreated` (boolean)
- `data.aiOptions.runWhenRecordIsUpdated` (boolean)
- `data.createdAt` (string)
- `data.updatedAt` (string)
```json
{
"data": {
"id": "",
"name": "",
"description": "",
"type": "SINGLE_LINE_TEXT",
"options": {},
"allowMultipleEntries": true,
"readonly": true,
"required": true,
"locked": true,
"defaultValue": "",
"aiOptions": {
"aiFillable": true,
"aiOnly": true,
"allowWebSearch": true,
"aiModel": "",
"prompt": "",
"canBeTriggeredManually": true,
"runWhenRecordIsCreated": true,
"runWhenRecordIsUpdated": true
},
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
}
```
### 429: Rate limit exceeded.
No response body.
## Request example
```bash
curl --request GET \
--url 'https://tables-api.softr.io/api/v1/databases//tables//fields/' \
--header 'Softr-Api-Key: '
```
---
# Add Table Field
Source: https://docs.softr.io/softr-api/softr-database-api/table-fields/add-table-field
## Field Types Reference
### Editable Fields
| Type | Value Format | Description |
| ------------------ | ------------------- | ---------------------------------------------- |
| `SINGLE_LINE_TEXT` | `string` | Short text |
| `LONG_TEXT` | `string` | Multi-line text |
| `EMAIL` | `string` | Email address |
| `PHONE` | `string` | Phone number |
| `URL` | `string` | Web URL |
| `NUMBER` | `number` | Numeric value |
| `CURRENCY` | `number` | Monetary amount |
| `PERCENT` | `number` | Percentage (0–100) |
| `RATING` | `number` | Star rating |
| `DURATION` | `number` | Duration |
| `CHECKBOX` | `boolean` | True/false |
| `SELECT` | `string` or `array` | Single or multi-select from predefined choices |
| `USER` | `object` or `array` | User reference |
| `LINKED_RECORD` | `string` or `array` | Link to record(s) in another table |
| `ATTACHMENT` | `object` or `array` | File attachment |
| `DATE` | `string` | Date (ISO 8601) |
| `DATETIME` | `string` | Date and time (ISO 8601) |
### Read-Only Fields
These are computed or system-managed and cannot be set when creating or updating records.
| Type | Description |
| ------------ | ------------------------------------ |
| `LOOKUP` | Value from a linked record's field |
| `ROLLUP` | Aggregation over linked records |
| `FORMULA` | Calculated from a formula expression |
| `CREATED_AT` | Record creation timestamp |
| `UPDATED_AT` | Record last modified timestamp |
| `CREATED_BY` | User who created the record |
| `UPDATED_BY` | User who last modified the record |
| `AUTONUMBER` | Auto-incrementing number |
| `RECORD_ID` | System record identifier |
## Field Options
Type-specific configuration passed in the `options` object when creating or updating fields.
### SELECT
```json
{
"choices": [
{ "id": "choice-1", "label": "Option A", "color": "#FF0000" },
{ "id": "choice-2", "label": "Option B", "color": "#00FF00" }
],
"allowToAddNewChoice": true,
"sorting": "CUSTOM",
"enforceOrder": false
}
```
`sorting` can be `CUSTOM`, `ALPHA_ASC`, or `ALPHA_DESC`.
### NUMBER
```json
{
"precision": 2,
"min": 0,
"max": 1000000,
"showThousandSeparator": true,
"thousandSeparatorLocale": "en-US",
"largeNumberAbbreviation": "NONE",
"prefix": null,
"suffix": null
}
```
`largeNumberAbbreviation` can be `NONE`, `K`, `M`, `B`, or `T`.
### CURRENCY
```json
{
"precision": 2,
"min": null,
"max": null,
"isoCode": "USD",
"customSymbol": null,
"showAs": "SYMBOL",
"showThousandSeparator": true,
"thousandSeparatorLocale": "en-US",
"largeNumberAbbreviation": "NONE",
"symbolOrCodePosition": "BEFORE"
}
```
- `showAs`: `SYMBOL` or `CODE`
- `symbolOrCodePosition`: `BEFORE` or `AFTER`
### LINKED\_RECORD
```json
{
"linkedTableId": "table-uuid",
"inverseLinkFieldId": "field-uuid",
"viewId": null,
"sorting": [],
"filter": null,
"enforceOrder": false
}
```
### LOOKUP
```json
{
"linkedRecordFieldId": "field-uuid",
"lookupFieldId": "field-uuid",
"isValid": true
}
```
### ROLLUP
```json
{
"linkedRecordFieldId": "field-uuid",
"rollupFieldId": "field-uuid",
"function": "SUM",
"filter": null
}
```
Available functions: `SUM`, `MIN`, `MAX`, `COUNT`, `AVERAGE`, `ARRAYCOMPACT`, `ARRAYJOIN`, `ARRAYUNIQUE`, `ARRAYFLATTEN`, `CONCATENATE`, `COUNTALL`, `COUNTA`, `OR`, `AND`.
### ATTACHMENT
```json
{
"showAs": "PREVIEW",
"inferredFileType": "OTHER",
"enableFileLinkExpiration": true,
"fileLinkExpirationValue": 2,
"fileLinkExpirationUnit": "HOURS"
}
```
- `showAs`: `PREVIEW`, `LIST`, or `BADGE`
- `inferredFileType`: `IMAGE`, `VIDEO`, `PDF`, `AUDIO`, or `OTHER`
- `fileLinkExpirationUnit`: `HOURS` or `MINUTES`
### FORMULA
```json
{
"formula": "IF({Status} = 'Active', {Amount} * 1.1, {Amount})",
"isValid": true,
"referencedFieldIds": ["field-uuid-1", "field-uuid-2"]
}
```
## AI Options
Fields can include an `aiOptions` object that configures AI-powered auto-fill behavior. This is returned in field definitions and can be set when creating or updating fields.
```json
{
"aiFillable": true,
"aiOnly": false,
"allowWebSearch": true,
"aiModel": "GPT_4_1",
"prompt": "Summarize the customer's request based on {Description}",
"canBeTriggeredManually": true,
"runWhenRecordIsCreated": true,
"runWhenRecordIsUpdated": false
}
```
| Property | Type | Default | Description |
| ------------------------ | ------- | ----------- | ----------------------------------------------------------- |
| `aiFillable` | boolean | `false` | Whether AI can fill this field |
| `aiOnly` | boolean | `true` | If `true`, only AI can write to this field |
| `allowWebSearch` | boolean | `false` | Allow AI to use web search when filling |
| `aiModel` | string | `"GPT_4_1"` | AI model to use |
| `prompt` | string | `""` | Prompt template (reference other fields with `{FieldName}`) |
| `canBeTriggeredManually` | boolean | `true` | Whether users can trigger AI fill manually |
| `runWhenRecordIsCreated` | boolean | `true` | Auto-run when record is created |
| `runWhenRecordIsUpdated` | boolean | `true` | Auto-run when record is updated |
Fields without AI configuration return `"aiOptions": null`.
## Endpoint
`POST https://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}/fields`
Add a new field to a table.
## Authorizations
- `Softr-Api-Key` (API key, header, required)
## Path parameters
- `databaseId` (string, required)
- `tableId` (string, required)
## Body (application/json)
- `name` (string, required)
- `type` (string, required)
- `options` (Record)
## Responses
### 200: The newly created field.
- `data` (object)
- `data.id` (string)
- `data.name` (string)
- `data.description` (string | null): Optional description of the field.
- `data.type` (enum): The type of the field. One of: `SINGLE_LINE_TEXT`, `CHECKBOX`, `CURRENCY`, `DATE`, `DATETIME`, `DURATION`, `EMAIL`, `SELECT`, `NUMBER`, `ATTACHMENT`, `RATING`, `LINKED_RECORD`, `LONG_TEXT`, `URL`, `PERCENT`, `PHONE`, `LOOKUP`, `ROLLUP`, `FORMULA`, `CREATED_AT`, `UPDATED_AT`, `CREATED_BY`, `UPDATED_BY`, `AUTONUMBER`, `RECORD_ID`, `USER`.
- `data.options` (Record): Configuration options for the field, specific to its type. See the official documentation for the structure of each type.
- `data.allowMultipleEntries` (boolean)
- `data.readonly` (boolean)
- `data.required` (boolean)
- `data.locked` (boolean)
- `data.defaultValue` (string | null)
- `data.aiOptions` (object | null): AI-powered auto-fill configuration. Null if not configured.
- `data.aiOptions.aiFillable` (boolean)
- `data.aiOptions.aiOnly` (boolean)
- `data.aiOptions.allowWebSearch` (boolean)
- `data.aiOptions.aiModel` (string)
- `data.aiOptions.prompt` (string)
- `data.aiOptions.canBeTriggeredManually` (boolean)
- `data.aiOptions.runWhenRecordIsCreated` (boolean)
- `data.aiOptions.runWhenRecordIsUpdated` (boolean)
- `data.createdAt` (string)
- `data.updatedAt` (string)
```json
{
"data": {
"id": "",
"name": "",
"description": "",
"type": "SINGLE_LINE_TEXT",
"options": {},
"allowMultipleEntries": true,
"readonly": true,
"required": true,
"locked": true,
"defaultValue": "",
"aiOptions": {
"aiFillable": true,
"aiOnly": true,
"allowWebSearch": true,
"aiModel": "",
"prompt": "",
"canBeTriggeredManually": true,
"runWhenRecordIsCreated": true,
"runWhenRecordIsUpdated": true
},
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
}
```
### 429: Rate limit exceeded.
No response body.
## Request example
```bash
curl --request POST \
--url 'https://tables-api.softr.io/api/v1/databases//tables//fields' \
--header 'Softr-Api-Key: ' \
--header 'Content-Type: application/json' \
--data '{
"name": "",
"type": ""
}'
```
---
# Update Table Field
Source: https://docs.softr.io/softr-api/softr-database-api/table-fields/update-table-field
## Endpoint
`PUT https://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}/fields/{fieldId}`
Update the properties of a specific field.
## Authorizations
- `Softr-Api-Key` (API key, header, required)
## Path parameters
- `databaseId` (string, required)
- `tableId` (string, required)
- `fieldId` (string, required)
## Body (application/json)
- `name` (string)
- `type` (string)
- `options` (Record)
## Responses
### 200: The updated field.
- `data` (object)
- `data.id` (string)
- `data.name` (string)
- `data.description` (string | null): Optional description of the field.
- `data.type` (enum): The type of the field. One of: `SINGLE_LINE_TEXT`, `CHECKBOX`, `CURRENCY`, `DATE`, `DATETIME`, `DURATION`, `EMAIL`, `SELECT`, `NUMBER`, `ATTACHMENT`, `RATING`, `LINKED_RECORD`, `LONG_TEXT`, `URL`, `PERCENT`, `PHONE`, `LOOKUP`, `ROLLUP`, `FORMULA`, `CREATED_AT`, `UPDATED_AT`, `CREATED_BY`, `UPDATED_BY`, `AUTONUMBER`, `RECORD_ID`, `USER`.
- `data.options` (Record): Configuration options for the field, specific to its type. See the official documentation for the structure of each type.
- `data.allowMultipleEntries` (boolean)
- `data.readonly` (boolean)
- `data.required` (boolean)
- `data.locked` (boolean)
- `data.defaultValue` (string | null)
- `data.aiOptions` (object | null): AI-powered auto-fill configuration. Null if not configured.
- `data.aiOptions.aiFillable` (boolean)
- `data.aiOptions.aiOnly` (boolean)
- `data.aiOptions.allowWebSearch` (boolean)
- `data.aiOptions.aiModel` (string)
- `data.aiOptions.prompt` (string)
- `data.aiOptions.canBeTriggeredManually` (boolean)
- `data.aiOptions.runWhenRecordIsCreated` (boolean)
- `data.aiOptions.runWhenRecordIsUpdated` (boolean)
- `data.createdAt` (string)
- `data.updatedAt` (string)
```json
{
"data": {
"id": "",
"name": "",
"description": "",
"type": "SINGLE_LINE_TEXT",
"options": {},
"allowMultipleEntries": true,
"readonly": true,
"required": true,
"locked": true,
"defaultValue": "",
"aiOptions": {
"aiFillable": true,
"aiOnly": true,
"allowWebSearch": true,
"aiModel": "",
"prompt": "",
"canBeTriggeredManually": true,
"runWhenRecordIsCreated": true,
"runWhenRecordIsUpdated": true
},
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
}
```
### 429: Rate limit exceeded.
No response body.
## Request example
```bash
curl --request PUT \
--url 'https://tables-api.softr.io/api/v1/databases//tables//fields/' \
--header 'Softr-Api-Key: ' \
--header 'Content-Type: application/json' \
--data '{
"name": "",
"type": "",
"options": {}
}'
```
---
# Delete Table Field
Source: https://docs.softr.io/softr-api/softr-database-api/table-fields/delete-table-field
## Endpoint
`DELETE https://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}/fields/{fieldId}`
Delete a specific field from a table.
## Authorizations
- `Softr-Api-Key` (API key, header, required)
## Path parameters
- `databaseId` (string, required)
- `tableId` (string, required)
- `fieldId` (string, required)
## Responses
### 204: Field deleted successfully.
No response body.
### 429: Rate limit exceeded.
No response body.
## Request example
```bash
curl --request DELETE \
--url 'https://tables-api.softr.io/api/v1/databases//tables//fields/' \
--header 'Softr-Api-Key: '
```
---
# Get Records
Source: https://docs.softr.io/softr-api/softr-database-api/records/get-records
## Endpoint
`GET https://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}/records`
Retrieve a list of all records in the specified table.
## Authorizations
- `Softr-Api-Key` (API key, header, required)
## Path parameters
- `databaseId` (string, required)
- `tableId` (string, required)
## Query parameters
- `offset` (integer, default: 0)
- `limit` (integer, default: 10)
- `fieldNames` (boolean, default: false): If true, use field names as keys in the fields object instead of field IDs.
- `viewId` (string): Filter records by a specific view.
## Responses
### 200: A paginated list of records.
- `data` (object[])
- `data.id` (string)
- `data.tableId` (string)
- `data.fields` (Record): A map of Field IDs to their values for this record.
- `data.createdAt` (string)
- `data.updatedAt` (string)
- `metadata` (object)
- `metadata.offset` (integer)
- `metadata.limit` (integer)
- `metadata.total` (integer)
```json
{
"data": [
{
"id": "",
"tableId": "",
"fields": {},
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
],
"metadata": {
"offset": 123,
"limit": 123,
"total": 123
}
}
```
### 429: Rate limit exceeded.
No response body.
## Request example
```bash
curl --request GET \
--url 'https://tables-api.softr.io/api/v1/databases//tables//records' \
--header 'Softr-Api-Key: '
```
---
# Search Records
Source: https://docs.softr.io/softr-api/softr-database-api/records/search-records
## Filtering Guide
The Search Records endpoint lets you filter, sort, and paginate records using a JSON request body. All three top-level fields (`filter`, `sorting`, `paging`) are optional.
```json
{
"paging": {
"offset": 0,
"limit": 50
},
"sorting": [
{ "sortingField": "field-uuid", "sortType": "ASC" }
],
"filter": {
"condition": { ... }
}
}
```
### Filter Condition Types
Filters are passed in `filter.condition`. There are four types, determined by the operator.
#### Binary Conditions
Compare a field to a value:
```json
{
"operator": "CONTAINS",
"leftSide": "field-uuid",
"rightSide": "search term"
}
```
| Operator | Description | Right Side |
| ------------------------ | ----------------------------- | -------------- |
| `IS` | Equals | single value |
| `IS_NOT` | Not equals | single value |
| `GREATER_THAN` | Greater than | number or date |
| `GREATER_THAN_OR_EQUALS` | Greater than or equal | number or date |
| `LESS_THAN` | Less than | number or date |
| `LESS_THAN_OR_EQUALS` | Less than or equal | number or date |
| `CONTAINS` | String contains | string |
| `DOES_NOT_CONTAIN` | String does not contain | string |
| `STARTS_WITH` | String starts with | string |
| `DOES_NOT_START_WITH` | String does not start with | string |
| `ENDS_WITH` | String ends with | string |
| `DOES_NOT_END_WITH` | String does not end with | string |
| `IS_ONE_OF` | Value is one of | array |
| `IS_NOT_ONE_OF` | Value is none of | array |
| `HAS_ANY_OF` | Multi-value field has any of | array |
| `HAS_ALL_OF` | Multi-value field has all of | array |
| `HAS_NONE_OF` | Multi-value field has none of | array |
#### Unary Conditions
Check whether a field is empty — no `rightSide` needed:
```json
{
"operator": "IS_EMPTY",
"leftSide": "field-uuid"
}
```
| Operator | Description |
| -------------- | ------------------ |
| `IS_EMPTY` | Field has no value |
| `IS_NOT_EMPTY` | Field has a value |
#### Ternary Conditions
Range-based checks with `lowerBound` and `upperBound`:
```json
{
"operator": "IS_BETWEEN",
"leftSide": "field-uuid",
"lowerBound": 10,
"upperBound": 100
}
```
| Operator | Description |
| ---------------- | ----------------------------------- |
| `IS_BETWEEN` | Value is between bounds (inclusive) |
| `IS_NOT_BETWEEN` | Value is outside bounds |
| `IS_WITHIN` | Date is within a relative range |
| `IS_NOT_WITHIN` | Date is outside a relative range |
#### Composite Conditions
Combine multiple conditions with `AND` or `OR`:
```json
{
"operator": "AND",
"conditions": [
{ "operator": "CONTAINS", "leftSide": "name-field", "rightSide": "acme" },
{ "operator": "GREATER_THAN", "leftSide": "amount-field", "rightSide": 1000 },
{
"operator": "OR",
"conditions": [
{ "operator": "IS", "leftSide": "status-field", "rightSide": "active" },
{ "operator": "IS_EMPTY", "leftSide": "archived-field" }
]
}
]
}
```
### Relative Date Values
For date fields, you can use relative date strings instead of fixed ISO 8601 dates:
| Format | Examples |
| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PREDEFINED:` | `PREDEFINED:TODAY`, `PREDEFINED:YESTERDAY`, `PREDEFINED:TOMORROW`, `PREDEFINED:THIS_WEEK`, `PREDEFINED:LAST_WEEK`, `PREDEFINED:THIS_MONTH`, `PREDEFINED:THIS_YEAR`, `PREDEFINED:NEXT_MONTH`, `PREDEFINED:PAST_MONTH`, `PREDEFINED:7_DAYS_AGO`, `PREDEFINED:30_DAYS_FROM_NOW` |
| `RELATIVE_DATE::` | `RELATIVE_DATE:THIS:WEEK`, `RELATIVE_DATE:PAST:MONTH`, `RELATIVE_DATE:NEXT:QUARTER`, `RELATIVE_DATE:PAST:7` (7 days ago) |
| ISO 8601 | `"2025-05-21"`, `"2025-05-21T20:00:00.000Z"` |
### Complete Example
Find active contacts named "acme" with an amount over 1000, created this month:
```json
{
"paging": { "offset": 0, "limit": 50 },
"sorting": [
{ "sortingField": "amount-field-uuid", "sortType": "DESC" }
],
"filter": {
"condition": {
"operator": "AND",
"conditions": [
{ "operator": "CONTAINS", "leftSide": "name-field-uuid", "rightSide": "acme" },
{ "operator": "GREATER_THAN", "leftSide": "amount-field-uuid", "rightSide": 1000 },
{ "operator": "IS", "leftSide": "status-field-uuid", "rightSide": "active" },
{ "operator": "IS_WITHIN", "leftSide": "created-at-field-uuid", "lowerBound": "RELATIVE_DATE:THIS:MONTH", "upperBound": "PREDEFINED:TODAY" }
]
}
}
}
```
## Endpoint
`POST https://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}/records/search`
Search for records in the specified table based on filter, sort, and pagination criteria.
## Authorizations
- `Softr-Api-Key` (API key, header, required)
## Path parameters
- `databaseId` (string, required)
- `tableId` (string, required)
## Query parameters
- `fieldNames` (boolean, default: false): If true, use field names as keys in the fields object instead of field IDs.
## Body (application/json)
- `filter` (object)
- `filter.condition` (object): A condition for filtering records. Text-related conditions are case-insensitive.
- `filter.condition.operator` (enum) One of: `AND`, `OR`, `IS_EMPTY`, `IS_NOT_EMPTY`, `IS_BETWEEN`, `IS_NOT_BETWEEN`, `IS_WITHIN`, `IS_NOT_WITHIN`, `IS`, `IS_NOT`, `GREATER_THAN`, `GREATER_THAN_OR_EQUALS`, `LESS_THAN`, `LESS_THAN_OR_EQUALS`, `CONTAINS`, `DOES_NOT_CONTAIN`, `STARTS_WITH`, `DOES_NOT_START_WITH`, `ENDS_WITH`, `DOES_NOT_END_WITH`, `IS_ONE_OF`, `IS_NOT_ONE_OF`, `HAS_ANY_OF`, `HAS_ALL_OF`, `HAS_NONE_OF`.
- `filter.condition.leftSide` (string): The Field ID to apply the operator on.
- `filter.condition.rightSide` (string | number | boolean | string[]): The value to compare against. Can be a string, number, or an array for operators like IS_ONE_OF.
- `filter.condition.lowerBound` (string): Lower bound for IS_BETWEEN operator.
- `filter.condition.upperBound` (string): Upper bound for IS_BETWEEN operator.
- `filter.condition.conditions` (object[]): Used for AND/OR operators to nest conditions.
- `filter.condition.conditions.operator` (enum) One of: `AND`, `OR`, `IS_EMPTY`, `IS_NOT_EMPTY`, `IS_BETWEEN`, `IS_NOT_BETWEEN`, `IS_WITHIN`, `IS_NOT_WITHIN`, `IS`, `IS_NOT`, `GREATER_THAN`, `GREATER_THAN_OR_EQUALS`, `LESS_THAN`, `LESS_THAN_OR_EQUALS`, `CONTAINS`, `DOES_NOT_CONTAIN`, `STARTS_WITH`, `DOES_NOT_START_WITH`, `ENDS_WITH`, `DOES_NOT_END_WITH`, `IS_ONE_OF`, `IS_NOT_ONE_OF`, `HAS_ANY_OF`, `HAS_ALL_OF`, `HAS_NONE_OF`.
- `filter.condition.conditions.leftSide` (string): The Field ID to apply the operator on.
- `filter.condition.conditions.rightSide` (string | number | boolean | string[]): The value to compare against. Can be a string, number, or an array for operators like IS_ONE_OF.
- `filter.condition.conditions.lowerBound` (string): Lower bound for IS_BETWEEN operator.
- `filter.condition.conditions.upperBound` (string): Upper bound for IS_BETWEEN operator.
- `filter.condition.conditions.conditions` (object[]): Used for AND/OR operators to nest conditions.
- `filter.condition.conditions.conditions.operator` (enum) One of: `AND`, `OR`, `IS_EMPTY`, `IS_NOT_EMPTY`, `IS_BETWEEN`, `IS_NOT_BETWEEN`, `IS_WITHIN`, `IS_NOT_WITHIN`, `IS`, `IS_NOT`, `GREATER_THAN`, `GREATER_THAN_OR_EQUALS`, `LESS_THAN`, `LESS_THAN_OR_EQUALS`, `CONTAINS`, `DOES_NOT_CONTAIN`, `STARTS_WITH`, `DOES_NOT_START_WITH`, `ENDS_WITH`, `DOES_NOT_END_WITH`, `IS_ONE_OF`, `IS_NOT_ONE_OF`, `HAS_ANY_OF`, `HAS_ALL_OF`, `HAS_NONE_OF`.
- `filter.condition.conditions.conditions.leftSide` (string): The Field ID to apply the operator on.
- `filter.condition.conditions.conditions.rightSide` (string | number | boolean | string[]): The value to compare against. Can be a string, number, or an array for operators like IS_ONE_OF.
- `filter.condition.conditions.conditions.lowerBound` (string): Lower bound for IS_BETWEEN operator.
- `filter.condition.conditions.conditions.upperBound` (string): Upper bound for IS_BETWEEN operator.
- `filter.condition.conditions.conditions.conditions` (object[]): Used for AND/OR operators to nest conditions.
- `filter.condition.conditions.conditions.conditions.operator` (enum) One of: `AND`, `OR`, `IS_EMPTY`, `IS_NOT_EMPTY`, `IS_BETWEEN`, `IS_NOT_BETWEEN`, `IS_WITHIN`, `IS_NOT_WITHIN`, `IS`, `IS_NOT`, `GREATER_THAN`, `GREATER_THAN_OR_EQUALS`, `LESS_THAN`, `LESS_THAN_OR_EQUALS`, `CONTAINS`, `DOES_NOT_CONTAIN`, `STARTS_WITH`, `DOES_NOT_START_WITH`, `ENDS_WITH`, `DOES_NOT_END_WITH`, `IS_ONE_OF`, `IS_NOT_ONE_OF`, `HAS_ANY_OF`, `HAS_ALL_OF`, `HAS_NONE_OF`.
- `filter.condition.conditions.conditions.conditions.leftSide` (string): The Field ID to apply the operator on.
- `filter.condition.conditions.conditions.conditions.rightSide` (string | number | boolean | string[]): The value to compare against. Can be a string, number, or an array for operators like IS_ONE_OF.
- `filter.condition.conditions.conditions.conditions.lowerBound` (string): Lower bound for IS_BETWEEN operator.
- `filter.condition.conditions.conditions.conditions.upperBound` (string): Upper bound for IS_BETWEEN operator.
- `filter.condition.conditions.conditions.conditions.conditions` (object[]): Used for AND/OR operators to nest conditions.
- `filter.condition.conditions.conditions.conditions.conditions.operator` (enum) One of: `AND`, `OR`, `IS_EMPTY`, `IS_NOT_EMPTY`, `IS_BETWEEN`, `IS_NOT_BETWEEN`, `IS_WITHIN`, `IS_NOT_WITHIN`, `IS`, `IS_NOT`, `GREATER_THAN`, `GREATER_THAN_OR_EQUALS`, `LESS_THAN`, `LESS_THAN_OR_EQUALS`, `CONTAINS`, `DOES_NOT_CONTAIN`, `STARTS_WITH`, `DOES_NOT_START_WITH`, `ENDS_WITH`, `DOES_NOT_END_WITH`, `IS_ONE_OF`, `IS_NOT_ONE_OF`, `HAS_ANY_OF`, `HAS_ALL_OF`, `HAS_NONE_OF`.
- `filter.condition.conditions.conditions.conditions.conditions.leftSide` (string): The Field ID to apply the operator on.
- `filter.condition.conditions.conditions.conditions.conditions.rightSide` (string | number | boolean | string[]): The value to compare against. Can be a string, number, or an array for operators like IS_ONE_OF.
- `filter.condition.conditions.conditions.conditions.conditions.lowerBound` (string): Lower bound for IS_BETWEEN operator.
- `filter.condition.conditions.conditions.conditions.conditions.upperBound` (string): Upper bound for IS_BETWEEN operator.
- `filter.condition.conditions.conditions.conditions.conditions.conditions` (object[]): Used for AND/OR operators to nest conditions.
- `sorting` (object[])
- `sorting.sortingField` (string): The Field ID to apply the sorting on
- `sorting.sortType` (enum) One of: `ASC`, `DESC`.
- `paging` (object)
- `paging.offset` (integer, default: 0)
- `paging.limit` (integer, default: 10)
## Responses
### 200: A paginated list of matching records.
- `data` (object[])
- `data.id` (string)
- `data.tableId` (string)
- `data.fields` (Record): A map of Field IDs to their values for this record.
- `data.createdAt` (string)
- `data.updatedAt` (string)
- `metadata` (object)
- `metadata.offset` (integer)
- `metadata.limit` (integer)
- `metadata.total` (integer)
```json
{
"data": [
{
"id": "",
"tableId": "",
"fields": {},
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
],
"metadata": {
"offset": 123,
"limit": 123,
"total": 123
}
}
```
### 429: Rate limit exceeded.
No response body.
## Request example
```bash
curl --request POST \
--url 'https://tables-api.softr.io/api/v1/databases//tables//records/search' \
--header 'Softr-Api-Key: ' \
--header 'Content-Type: application/json' \
--data '{
"filter": {
"condition": {
"operator": "AND",
"leftSide": "",
"rightSide": "",
"lowerBound": "",
"upperBound": "",
"conditions": [
{}
]
}
},
"sorting": [
{
"sortingField": "",
"sortType": "ASC"
}
],
"paging": {
"offset": 0,
"limit": 10
}
}'
```
---
# Get Single Record
Source: https://docs.softr.io/softr-api/softr-database-api/records/get-single-record
## Endpoint
`GET https://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}/records/{recordId}`
Retrieve details of a specific record by its ID.
## Authorizations
- `Softr-Api-Key` (API key, header, required)
## Path parameters
- `databaseId` (string, required)
- `tableId` (string, required)
- `recordId` (string, required)
## Query parameters
- `fieldNames` (boolean, default: false): If true, use field names as keys in the fields object instead of field IDs.
## Responses
### 200: Record details.
- `data` (object)
- `data.id` (string)
- `data.tableId` (string)
- `data.fields` (Record): A map of Field IDs to their values for this record.
- `data.createdAt` (string)
- `data.updatedAt` (string)
```json
{
"data": {
"id": "",
"tableId": "",
"fields": {},
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
}
```
### 429: Rate limit exceeded.
No response body.
## Request example
```bash
curl --request GET \
--url 'https://tables-api.softr.io/api/v1/databases//tables//records/' \
--header 'Softr-Api-Key: '
```
---
# Create Record
Source: https://docs.softr.io/softr-api/softr-database-api/records/create-record
## Endpoint
`POST https://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}/records`
Create a new record in the specified table.
## Authorizations
- `Softr-Api-Key` (API key, header, required)
## Path parameters
- `databaseId` (string, required)
- `tableId` (string, required)
## Query parameters
- `fieldNames` (boolean, default: false): If true, use field names as keys in the response fields object instead of field IDs.
## Body (application/json)
- `fields` (Record): A map of Field IDs to their values.
## Responses
### 200: The newly created record.
- `data` (object)
- `data.id` (string)
- `data.tableId` (string)
- `data.fields` (Record): A map of Field IDs to their values for this record.
- `data.createdAt` (string)
- `data.updatedAt` (string)
```json
{
"data": {
"id": "",
"tableId": "",
"fields": {},
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
}
```
### 429: Rate limit exceeded.
No response body.
## Request example
```bash
curl --request POST \
--url 'https://tables-api.softr.io/api/v1/databases//tables//records' \
--header 'Softr-Api-Key: ' \
--header 'Content-Type: application/json' \
--data '{
"fields": {}
}'
```
---
# Update Record
Source: https://docs.softr.io/softr-api/softr-database-api/records/update-record
## Endpoint
`PATCH https://tables-api.softr.io/api/v1/databases/{databaseId}/tables/{tableId}/records/{recordId}`
Partially update a specific record by its ID. Only the fields provided in the request body will be changed.
## Authorizations
- `Softr-Api-Key` (API key, header, required)
## Path parameters
- `databaseId` (string, required)
- `tableId` (string, required)
- `recordId` (string, required)
## Query parameters
- `fieldNames` (boolean, default: false): If true, use field names as keys in the response fields object instead of field IDs.
## Body (application/json)
- `fields` (Record): A map of Field IDs to their new values.
## Responses
### 200: The updated record.
- `data` (object)
- `data.id` (string)
- `data.tableId` (string)
- `data.fields` (Record): A map of Field IDs to their values for this record.
- `data.createdAt` (string)
- `data.updatedAt` (string)
```json
{
"data": {
"id": "",
"tableId": "
** tag. Within the **\
** element, you can link external resources, add metadata as well as custom styles. The second piece will be added at the end of your **\