# Added Value
Source: https://docs.less.tech/academy/beginner/added-value
You will very often find yourself wanting to add new columns to your dataset. In this lesson, we'll cover the [New Column](/tools/new/columns) tool. This is a very versatile tool that can be used in a lot of different ways.
## Exercise
We're working with the *ORDERS* dataset and you want to get the result shown below. We ended up with 227.597 rows and used five tools to get the result.
A couple of hints. You can round numeric columns in a couple of ways: with the [Transform](/tools/basics/transform) tool or with the [.ROUND](/canvas/syntax/syntax-operations) syntax. The [TEXT()](/canvas/syntax/syntax-functions) function could also be helpful to convert a number to a string - you can also use the Column tool if you prefer.
We use a 0.85 exchange rate to go from USD to EUR. We only want orders that are currently fulfilled (*F* in the *O\_ORDERSTATUS* column) and where the order is placed on or after 1994-01-01 and before or on 1994-12-31.
## Solution
# IF all ELSE fails
Source: https://docs.less.tech/academy/beginner/if-all-else-fails
IF statements - or conditional statements - are a very powerful ways to create new columns. They allow you to set up a bunch of rules that you can use to create new columns. Like the example below.
In Less, we create these using the [IF Column](/tools/new-columns/if-column) tool - which is exactly what this lesson is about.
## Exercise
We're working with the *ORDERS* dataset and you want to get the result shown below. We ended up with 282 rows and used eight tools to get the result.
We're trying to understand which of our clerks have orders that demand immediate attention. We want to give them this dataset so they'll know what to focus on.
Some notes:
1. On your way to the results, you should create two new columns using the [IF Column](/tools/new-columns/if-column) tool.
2. The first column should take the order status - which is abbreviated to a single letter - and convert it to a full word. O for Ordered, F for Fulfilled and P for Processed.
3. The second column should determine order urgency - either High, Medium or Low. Orders with a total price above 400.000 should be High, orders with a total price higher than 200.000 should be Medium and all others should be Low.
4. We are only interested in orders with a high value (the column we just created), with urgent priority (*O\_ORDERPRIORITY* column) that are ordered (the other column we just created).
5. When it comes to the *OrdersToPayAttentionTo* column, the concatenate aggregation method for Text columns in the [Group By](/tools/reshape/group-by) tool is your friend.
6. We want the data to be sorted by the number of orders to pay attention to, descending.
### Solution
# It's a Date
Source: https://docs.less.tech/academy/beginner/its-a-date
You'll very often find yourself working with dates. In this lesson, we'll cover a number of the different tools you can use to do that in Less.
We'll show you how you can use a [Date Transform](/tools/new-columns/date-transform) tool to get a certain format out of a date column; how to use a [Date Difference](/tools/new-columns/date-difference) tool to get the difference between two dates; why the [Count Business Days](/tools/new-columns/count-business-days) tool is perhaps better; we'll demonstrate a [Date Math](/tools/new-columns/date-math) tool to add or subtract a number of days from a date.
## Exercise
We're working with the first 1.000.000 rows in the *LINEITEM* dataset (limit this in the Input tool) and you want to get the result shown below.
We're starting to get to a point where you can solve the exercises in a number of different ways. We used the Combine, Count Business Days, Date Transform, IF Column, Group By and Filter tools, but maybe you'll come up with a different way.
We ended up with 2 rows and used 13 tools to get the result.
We're interested in seing how many of our orders have been delivered late in 1995 and 1996. To do that, we created some arbitrary targets for each of our shipment modes with a [Manual Input](/tools/utilities/manual-input) tool that look like this:
An order is late **if** the number of [business days](/tools/new-columns/count-business-days) between the *SHIPDATE* and *RECEIPTDATE* columns is greater than the target for the corresponding shipment mode (*if* is often the keyword for a [IF Column](/tools/new-columns/if-column) tool)
Note that we're using Holidays in the US with all optional Holiday Categories turned on ([Count Business Days](/tools/new-columns/count-business-days) tool)
You probably also want to use the [Combine](/tools/new-tools/combine) tool to merge this made up dataset with our deliveryTargets with the *LINEITEM* dataset.
## Solution
# Join Forces
Source: https://docs.less.tech/academy/beginner/join-forces
One of the most useful tools in your toolbox is to merge dataset. To that end, we have a couple of quite neat tools: [Combine](/tools/merge/combine), [Stack](/tools/merge/stack) and [Append](/tools/merge/append).
The Combine tool - which is perhaps the most valuable tool out there - merges two datasets by one or multiple IDs - it's like a SQL join or a XLOOKUP/VLOOKUP in Excel. The Stack tool stacks datasets on top of each other. The Append tool attaches a number of rows and columns to a different dataset.
## Exercise
We're working with the *NATION* and *REGION* datasets and you want to get the result shown below. We end up with eleven rows and used nine tools to get the result.
Note that we use all three tools (Combine, Append and Stack) to get the result. And you should too.
1. We start by combining the *NATION* and *REGION* datasets.
2. We use a [Manual Input](/tools/utilities/manual-input) tool to create a new small dataset. It contains two rows in a column called *filter* (EUROPE and AMERICA). We attach this and use a Filter to ensure that all our rows are either in Europe or America.
3. We use a second Manual Input tool to create a new small dataset. It contains one rows with two columns *country* (value = DENMARK) and *region* (value = EUROPE). We put this dataset on top of the original combined NATION+REGION dataset.
## Solution
# Less to do More
Source: https://docs.less.tech/academy/beginner/less-to-do-more
In this first lesson, we'll cover the [Filter](/tools/basics/filter), [Columns](/tools/basics/columns), [Group By](/tools/reshape/group-by) and [Sort](/tools/basics/sort) tools.
These are foundational tools that every person working with data will use very frequently.
## Exercise
We're working with the *ORDERS* dataset. We only want orders that are currrently ordered (*O* in the *O\_ORDERSTATUS* column) and the task is to get the result shown below. We ended up with 5 rows and used five tools to get the result.
*orders* is a count of the transactions and *volume* is a sum of the *O\_TOTALPRICE* column.
## Solution
# Mind Your Language
Source: https://docs.less.tech/academy/beginner/mind-your-language
Syntax is a quite powerful way to reduce the amount of tools you need to use to get to your result. You can read much more about it in the [Syntax](/canvas/syntax-quickstart) section.
In this lesson, we'll dive into the different types of syntaxes and how to use them.
## Exercise
We're working with the *Example\_Dataset* dataset and you want to get the result shown below. Our result contains five rows and we used three tools to get the result.
You are supposed to only use a single New Column tool to add the *syntaxing* column. Here's logic of how we create it.
1. Think of this in steps. You can perhaps start by creating each step with an individual New Column tool and then consolidate them at the end
2. We using a conditional statement syntax to create the *syntaxing* column.
3. We specify that the *date\_string* should be a datetime value. Then we add the number of days in the *int\_col* column to it.
4. If it is larger than todays date (our date is Oct 6, 2025), then we multiply the *simple\_int* column with the nulls\_col if it is not null and one if it is null (maybe COALESCE?).
If it is not larger than todays date, then we create a NULL value
## Solution
# Test: Where's the Money
Source: https://docs.less.tech/academy/beginner/wheres-the-money
Your first real challenge! This is where you'll learn to use your skills to solve a real-world problem.
In the challenge, we want you to help us find out how much money we made in each our market segments. We only want to look at **1)** orders in 1995, **2)** ordered orders (in the *O\_ORDERSTATUS* column) and **3)** where customers are in Europe.
You should try to solve this challenge with as few tools as possible. You will most likely use Columns, Filters, Group By, Combine, New Column and IF Column. You should use the *ORDERS*, *CUSTOMERS*, *NATION* and *REGIONS* tables.
We did it with 20 tools, but we're pretty sure you can do it with less.
This is the result you should get (55 rows x 3 columns):
If you're a really cool and intelligent person, you could even get to this result (11 rows x 6 columns - hint: [Pivot](/tools/reshape/pivot))
## Solution
# Learning Less
Source: https://docs.less.tech/academy/introduction
Become a Less expert!
It can be intimidating to learn a new tool, but you've come to the right place. This is a guide to help you get started with Less.
We guarantee you that by the end of this guide, you'll be able on a Data Analyst fast track.
In the *Beginner* section, we'll cover the basics. You'll learn how to [clean, filter and aggregate](/academy/beginner/less-to-do-more) your data. You will learn [conditional statements](/academy/beginner/if-all-else-fails), [calculating columns](/academy/beginner/added-value), [merge datasets](/academy/beginner/join-forces), [syntaxing](/academy/beginner/mind-your-language) and [working with dates](/academy/beginner/its-a-date).
### How it works
We'll provide you with the data that you need. Each lesson contains a video where we first walk through the relevant tools. After that, there's an exercise for you to complete. You can see the solution at the end of the video.
At the end of each section, there's a larger test where we'll use most of the tools you've learned in a more realistic scenario.
### Data
Every new workspace in Less comes with a Sample Data source which contains all the data you need to follow the lessons.
It might not be shared with you. If that's the case, you can download the data (all Parquet files) here:
1. [Customers](https://less-application.s3.eu-central-1.amazonaws.com/samples/CUSTOMER)
2. [Orders](https://less-application.s3.eu-central-1.amazonaws.com/samples/ORDERS)
3. [Line Items](https://less-application.s3.eu-central-1.amazonaws.com/samples/LINEITEM)
4. [Nation](https://less-application.s3.eu-central-1.amazonaws.com/samples/NATION)
5. [Region](https://less-application.s3.eu-central-1.amazonaws.com/samples/REGION)
And the examples data that is used in some of the lessons can be found [here](https://less-application.s3.eu-central-1.amazonaws.com/samples/examples_data).
Use a [File](/sources/guides/files) source to upload it into your workspace.
# Audit Log
Source: https://docs.less.tech/admin/audit-log
Monitor platform activity
As an Admin or Super Admin, you can view the audit log for all platform activity. We include the following activities:
* Asset creation
* Asset update
* Asset deletion
* Table read
* Table write
* Publish version
* Model view
* Login
Please get in touch if you have ideas for other activities to be included in the audit log.
You can view the relevant user, their IP address, the time of the activity, the entity (e.g table or asset), the entity ID and the details of the event.
Everything is searchable and filterable.
# Credits
Source: https://docs.less.tech/admin/credits
Billing overview
You can read about credits in general [here](/essentials/credits).
From the Credits tab in the Settings page, you can deep dive into the details of your credits are spent.
You can change the time period, see credits by date, view each job or session individually or aggregated by the asset or user over the given time period.
# Members
Source: https://docs.less.tech/admin/members
As an Admin or Super Admin, you can manage members of your workspace. The workspace owner can not be edited by other Admins or Super Admins.
When you invite new members you can choose if a new user should be an Admin, Super Admin or a Creator. **Admins** can access and edit all tabs in the Settings page. **Super Admins** can create new Admins. **Creators** are not able to create or edit anything on the platform. Disabling the Creator functionality is built for things like externalauditors and equivalent.
# Notifications
Source: https://docs.less.tech/admin/notifications
Get email alerts when connections and models fail
As an Admin or Super Admin, you can opt in to get notifications for all assets.
### Slack Notifications
From the *Notifications* tab in the Settings page, you can enable Slack notifications for all assets. First connect your Slack workspace to Less and select the channel that you want to receive notifications. Note that all members of the channel will receive the notifications.
You can choose if you want notifications when an asset runs successfully, fails, or with a warning - or you can enable all three.
### Email Notifications
You can also choose to personally get email notifications for all assets. Go the the Profile page and select the *Admin* tab. Here you can choose to get email notifications for all assets, or only for the assets that you created.
In the *Notifications* section, you can choose to get email notifications for the assets that you subscribe to. Read more [here](/guides/notifications).
# Platform
Source: https://docs.less.tech/admin/platform
Workspace-wide settings
On the Platform tab in the Settings page, you can manage your workspace-wide settings. Currently, the only setting available is to disable downloading data from anywhere in the workspace. For security-minded folks, this is a good way to prevent data from being downloaded and shared without your knowledge.
# Roles
Source: https://docs.less.tech/admin/roles
Manage workspace roles
You can read about roles in general [here](/guides/permissions-roles) and generally how permissions work [here](/guides/permissions-quickstart).
From the Roles tab in the Settings page, you can manage your workspace roles. You can create new roles, edit the abilities of the existing roles and delete roles.
# Execute asset
Source: https://docs.less.tech/api-reference/endpoint/executeAsset
api-reference/openapi.json POST /api/public/v1/assets/{assetId}/execute
Queue a run for a source, model, or orchestration
Starts a job for a **source**, **model**, or **orchestration**. Other asset types return an error. Send **`jobSource`** (for example `API` or `Manual`) and optional **`parameters`**; the job is always attributed to the authenticated user.
# Get asset
Source: https://docs.less.tech/api-reference/endpoint/getAsset
api-reference/openapi.json GET /api/public/v1/assets/{assetId}
Retrieve basic information about an asset
Look up an asset by ID: name, type, owner, folder, and schedules. This endpoint does not return secrets (for example connection passwords or credentials).
# Get job status
Source: https://docs.less.tech/api-reference/endpoint/getJob
api-reference/openapi.json GET /api/public/v1/jobs/{jobId}
Poll a run started via Execute asset or the app
Returns **status** (`pending`, `running`, `success`, `warning`, or `failed`), **assetId**, **jobSource**, and start/finish times. You only see jobs for assets you can read; otherwise the response is **404** (same as “wrong id”).
Useful for tracking when a job has finished running for a custom orchestration script.
# Get model (published version)
Source: https://docs.less.tech/api-reference/endpoint/getModel
api-reference/openapi.json GET /api/public/v1/assets/{assetId}/model
Published model version (full detail) for a model asset
Returns the **published** version for this model with the same JSON shape as `GET .../model/versions/{versionId}` (including **nodes**, **edges**, and **metadata**), or `null` if nothing is published yet.
# List assets
Source: https://docs.less.tech/api-reference/endpoint/listAssets
api-reference/openapi.json GET /api/public/v1/assets
List assets you can access
Returns a page of assets (name, type, owner, folder, schedules) with pagination. Connection secrets and credentials are never included.
Use `limit` and `offset` to walk the full list. Pass `folderId` (folder asset UUID) to return only assets in that folder; omit it to list across all folders you can access.
# Get model version
Source: https://docs.less.tech/api-reference/endpoint/modelVersion
api-reference/openapi.json GET /api/public/v1/assets/{assetId}/model/versions/{versionId}
Fetch one model version including the canvas
Returns a single model version, including **nodes**, **edges**, and **metadata** for the canvas. Model parameters and UI settings are not included.
Useful for a full documentation of a model configuration, i.e. all tool configurations, metadata flowing through the model and a graph through the edges object.
# List model versions
Source: https://docs.less.tech/api-reference/endpoint/modelVersions
api-reference/openapi.json GET /api/public/v1/assets/{assetId}/model/versions
List saved versions for a model
Returns a list of version records for a **model** asset. Draft and published versions are included; autosaves are not. Each item is a summary (no canvas graph). Use **Get model version** for full `nodes`, `edges`, and `metadata` for one version.
# Introduction
Source: https://docs.less.tech/api-reference/introduction
Use the Less API to fetch asset metadata, list model versions, and trigger runs.
The Less REST API enables you to programmatically interact with Less from third-party tools. All endpoints return JSON and live under `/api/public/v1`.
### Base URL
```
https:///api/public/v1
```
The default workspace host is `app.less.tech`. If your workspace uses a different host, use that instead. The endpoint playground on each page lets you set the server before sending a request.
### Authentication
Authenticate requests with an API key passed as a bearer token. You can create an API key from **Profile → API Keys**.
```http theme={null}
Authorization: Bearer
```
Missing or invalid tokens return `401 Unauthorized`.
### Endpoints
**Assets**
* [List assets](/api-reference/endpoint/listAssets) — Get all assets you can read (Folders, Models, Sources, Orchestrations)
* [Get asset](/api-reference/endpoint/getAsset) — Get a single asset by ID
* [Execute asset](/api-reference/endpoint/executeAsset) — Queue a run for a source, model, or orchestration
**Model versions**
* [List model versions](/api-reference/endpoint/modelVersions) — Get all versions for a model
* [Get model version](/api-reference/endpoint/modelVersion) — Get a single version by ID
* [Get published version](/api-reference/endpoint/getModel) — Get the currently published version of a model
**Jobs**
* [Get job status](/api-reference/endpoint/getJob) — Get the status and timing for a job
### Pagination
List endpoints are paginated with `limit` and `offset` query parameters:
* `limit` — page size. Default `50`, maximum `100`.
* `offset` — number of items to skip from the start of the sorted list. Default `0`.
[List assets](/api-reference/endpoint/listAssets) also accepts an optional `folderId` query parameter (folder asset UUID) to scope results to a single folder.
```
GET /api/public/v1/assets?limit=50&offset=100
GET /api/public/v1/assets?folderId=&limit=50
```
Responses include a `meta` object with the values used plus a `hasMore` flag:
```json theme={null}
{
"data": [ ... ],
"meta": { "limit": 50, "offset": 100, "hasMore": true }
}
```
Continue paging by incrementing `offset` by `limit` until `hasMore` is `false`.
# Adding Documentation
Source: https://docs.less.tech/canvas/adding-documentation
Adding documentation to your models is a great way to improve the understanding of your models and the data they produce.
There are two ways to add documentation to your models: using the tool annotations and using the [Comment](/tools/basics/comment) tool.
### Using the tool annotations
The tool annotations are helpful to add tool-specific documentation to your models. Annotations are attached to the tool itself and hence cannot be removed from the tool.
You can easily change the default annotations with your own documentation. If you remove your custom annoation, it reverts to the default.
In the "options" menu in the top right corner, you can choose whether you want to show 1) all annotations, 2) none or 3) custom annotations only.
### Using the Comment tool
The [Comment](/tools/basics/comment) tool is a great way to add documentation across multiple tools. Read more Comment tool [here](/tools/utilities/comment).
# Data Grid
Source: https://docs.less.tech/canvas/datagrid
View and interact with your data
### Overview
You can also easily see which tool you seeing data from. Similarly, you can see the number of rows and columns in the data grid.
### Data types
Data types are automatically detected and displayed in the data grid. Simply hover the icon to see the data type.
### Trailing spaces and tabs
If a cell contains trailing spaces, newlines or tabs, you can easily spot them. The text will be highlighted in red and you can hover to see what you need to pay attention to.
### Filtering
It might be helpful to inspect your data before you begin building your model. The data grid allows you to filter your data based on the values in the columns. Note that you're filtering the **full** dataset and not just the first page.
You can add multiple filters to the data grid that are all applied to the dataset.
### Sorting
Like filtering, it might be helpful to sort your data to get to know your data better. The data grid allows you to sort your data based on the values in the columns.
### Anchors
Some tools have multiple outputs - we call these anchors. For instance, a [Unique](/tools/basics/unique) contains two outputs: the unique values and the duplicate values. These anchors are also shown in the data grid and enable you to easily switch between the views.
[Combine](/tools/merge/combine), [Filter](/tools/basics/filter), [Unique](/tools/basics/unique), [Add Business Days](/tools/new-columns/add-business-days), [Count Business Days](/tools/new-columns/count-business-days) and the [Loop](/tools/utilities/loop) tool have multiple anchors.
### Pagination
You can navigate through the pages of the data grid using the pagination controls at the bottom-right of the data grid.
# Versions, Draft and Publish
Source: https://docs.less.tech/canvas/draft-publish
Saving your work
There are a couple of different ways to save your work: versions, draft, publish and auto saves. Technically, all of these are versions. They are just different types of versions.
You can view all your versions by navigating to the "options" menu in the top right corner and clicking "Show version log".
Whenever you open a new model, we save that this model now exists. As you continue to build your model, you should save your work via CMD/CTRL+SHIFT+S or through the "options" menu in the top right corner. This will save a draft of your work. If you at any point loose your work, we automatically create an auto-save every 30 seconds. We store up to 5 auto-saves per model per user.
A version is a snapshot of your work at a given point in time. The only difference between a version and a draft is that a comment is required for a version. We recommend using versions to summarize your work after completing a part of a model. It makes it easier to understand what you have done and to revert to a previous version if needed.
A published version also requires a comment. We recommend publishing when you have completed a model. **Only models with a published version can be scheduled**. The smart thing is that you can have a published version running on a schedule and still make changes to the model as a draft. Whenever you're ready to publish your model, you can simply publish the draft and it will overwrite the published version.
### A typical workflow
You start working on a model. Because you listen to our recommendation, you save it as a draft quite regularly.
You get to a point where you're happy with your work but the model is not quite ready. You save a version and attach a comment to it.
The next day, you begin working again and this time you finish your model. You publish the model, attach a comment to it and schedule it.
After a few days, one of your team members has a comment to the output. You open the published model, make a change and we'll automatically create a new draft for you. You work on that draft for a few days. In the mean time, the current published model runs without impact.
When you're ready to publish your adjusted model, you can simply publish the draft and it will overwrite the previous published version. Your new version is now the published and hence, scheduled version.
You can always access the last 5 auto-saves should you loose your work while building your model.
### See and compare versions
You can see and compare versions by navigating to the "options" menu in the top right corner and clicking "Show version log".
From there click on the version you want to see.
If you want to compare that version to another version, you can do so by clicking on the version you want to compare to and then the "Compare" button.
### Publishing models
You might now have the [permissions](/guides/permissions-quickstart) needed to publish a model. If you don't, you can request a member of your workspace who has the needed permissions to publish the model for you. They'll receive an email where they can view the currently published model and your requested changes.
They can either approve or reject the changes. You'll receive an email with the outcome of the review.
# Functionality
Source: https://docs.less.tech/canvas/functionality
We'll start with an overall run through of the Canvas. Below you can read more about additional options (the three dots in the top right corner).
1. **Exit** the Canvas (remember to save your work)
2. This is the **toolbar**. You can switch between the different tabs (Basics, New Columns, etc.) in the top and drag tools from the bottom to the Canvas.
3. When a process is running, you can stop it by clicking the **stop** button.
4. Use this to search for tools. You can search by name and tool ID.
5. Here you can **clear your cache**. This is useful if you're experiencing performance issues or if you want to start fresh.
6. This **runs all your tools**.
7. Use this to **save** your model. You can also used CMD/CTRL+SHIFT+S to save your model. Read more about saving your model [here](/canvas/draft-publish).
8. Click this to open the **chat support**.
9. Additional option - read more below.
10. Here we have our **model metrics**. You can see the number of rows, columns and tools. You also see the current CPU and Memory utilization - these are updated every 2nd second. Read more about CPU, Memory and instances [here](/canvas/instances).
11. This is the **metrics chart**. It tracks CPU and memory usage in real-time and updates every 2nd second.
12. This is a **minimap** of the Canvas. It shows your current view and you can drag it around to change your view.
13. This is a **tool**. On top, you see the tool status (running, stopped, etc.). When you get closer to it, it switches to a setting wheel - you can click this to open the tool configuration. If you click on a tool, you run that particular tool. Below, you see the tool ID and annotations. You can edit the annotation by clicking on it (see more about documentation [here](/canvas/adding-documentation)).
14. Here we have the **data** showing you the data you're working with. Learn more about the data grid [here](/canvas/datagrid).
### Additional options
By clicking the three dots in the top right corner, you can access additional options.
1. The first five options are related to version, saving, and draft/publish. Read more about that here [here](/canvas/draft-publish).
2. Here you can **rename** your model.
3. Change you **instance size** - read more about instances [here](/canvas/instances).
4. Use this to undo / redo your changes. You can also use CMD/CTRL+Z and CMD/CTRL+Y to undo / redo your changes.
5. Here you can fit your view to your tools - you can also use CMD/CTRL+F. You can also zoom in and out (also using CMD/CTRL++ and CMD/CTRL+0).
6. Customize your Canvas: you can show all/custom/no annotations, enable/disabled snap-to-grid, show/hide the toolbar, show/hide the metrics chart, show/hide the minimap and show/hide the datagrid.
7. Download your data as either a CSV or Excel file. File size is limited to 20.000.000 cells (rows \* columns) - anything above that will fail.
8. Use this to **restart your session**
9. Here you can **export** your model as JSON file or **import** a model.
10. Switch between light/dark mode.
# Instances and Benchmarking
Source: https://docs.less.tech/canvas/instances
Instances determine how much computation power is available for your model or source.
When working on the Canvas, you get a dedicated session for you to work in. This session is running on a certain instance size. You can see how much of the resources you're consuming in the top left corner and on the metrics charts.
If you see an error message that says "You don't have enough resources to run this model..", you should upgrade your instance to a larger size. You can do this from the Canvas by clikcing on the settings in the top right corner. Then click on the *Select instance* dropdown.
Less allows you to add more computation power whenever you need it. This is primarily useful if you need more computation power to handle large datasets but can also be effective if you want want to run a model faster.
The larger the instance you use, the more [credits](/essentials/credits) you will consume.
You can change the instance size at any time from the Canvas. Navigate to the Settings in the top right corner and use the *Select Instances* dropdown. At the top of the Canvas window you can see which session size is currently selected.
### Instances
You can choose from a number of different instance sizes. The instance size determines how much computational power is available for your model. The larger the instance, the more credits you consume.Read more about [credits](/essentials/credits).
### Benchmarking
Coming soon.
# Parameters
Source: https://docs.less.tech/canvas/parameters
A globally available variable store
Parameters is one of the features we love the most about Canvas. It allows you to create a variable that can be referenced in your model.
Imagine that you have a fixed exchange rate for your currency conversion and you want to use this rate in a bunch of different places in your model. You could create a parameter called 'exchange\_rate' and set it to the value of the exchange rate. Then you could reference this parameter in your model by using the parameter name. Instead of having to change it everywhere you use it, you can simply change it in the parameter and it will be updated everywhere.
Parameters can also be used to make your model more flexible and reusable. You could for instance dynamically load datasets with parameters and the [Directory](/tools/utilities/directory) tool and filter the datasets with parameters and the [Filter](/tools/basics/filter) tool.
### Using Parameters
Follow along in the demo below to see how you can use Parameters in your model.
You can also view the demo in full screen [here](https://app.arcade.software/share/gnUOg2olil3mI6gOa9ua).
# Quickstart
Source: https://docs.less.tech/canvas/quickstart
Quickstart to the Canvas
### Sessions
The first thing you need to know about when creating a new Canvas are **sessions**. When you open a new Canvas, we start creating a new session dedicate to you. A session is basically a server optimized for data analytics that we provide to you.
This is one of the smart things about Less. We give you computational resources when you need them. It also means that 1000 users can work independently in the same workspace without affecting each other.
It takes about 30-60 seconds to create a new session. When your session is ready, you'll see this 👇
This means that you can now start working on the Canvas. You can always restart your session by clicking on the options menu in the top right corner and selecting *Restart session*.
### Building a model
Now that you have your session, you can start building your model. That typically starts with an [Input](/tools/basics/input), [Directory](/tools/basics/directory) or [Manual Input](/tools/utilities/manual-input) tool.
You can also view the demo in full screen [here](https://app.arcade.software/share/lzTSwbJgiHBy54Xynbqr).
Read more about all the tools [here](/tools/basics/input). Check out the [Academy](/academy/introduction) if you want to get started building.
# Reserved Conventions
Source: https://docs.less.tech/canvas/reserved
There are a few conventions that are reserved by Less. You are not allowed to use them as table or column names.
No columns should be named anything starting with `[less]` or `[LESS]` or `[Less]`. This is considered reserved for internal use and violation will cause errors.
# Storing Data
Source: https://docs.less.tech/canvas/storing-data
Two methods for storing data in Canvas.
There are two methods for storing data in Canvas.
You can either use a [Save Tables](/tools/basics/save-tables) to store data in a table. This table will be available in other models. The table is stored on our secure infrastructure. Enterprise clients can self-host the storage if they want to.
Alternatively, you can set up a [Destination](/destinations/quickstart) and then use the [Destination](/tools/basics/destinations) tool to store and send your data to a destination. This destination can be a database like Snowflake, a worksheet like Google Sheets, or even an email like Gmail.
### Why is this smart?
There are several reasons why we think this setup is smart.
1. **Avoid cluttering you destinations**. If you use a database Destination like Snowflake, you can avoid storing unnecessary data in your database. Imagine you have a process of 10 models - each outputting one table. The first 9 models can store the table in Less and only the last model will store the table in the destination. Saves costs and avoids cluttering your database.
2. **Set once once, use everywhere**. If you set up a destination once, you can use it in all your models. You don't have to set it up in each model.
3. **Optimized for performance and data analytics**. Our storage is highly optimized for performance and data analytics. You don't have to spend time setting it up and you can start using it immediately.
# Constants
Source: https://docs.less.tech/canvas/syntax-constants
Returns the current datetime in UTC.
Returns a null value.
# Functions
Source: https://docs.less.tech/canvas/syntax-functions
Returns the first non-null value from a list of expressions. Evaluates expressions from left to right and returns the first one that is not null. If all expressions are null, returns null.
Conditional function/statement that returns one value if a condition is true, and another value if false. Can be nested within other IFF functions for complex conditional logic. Syntax: IFF(condition, value\_if\_true, value\_if\_false).
The condition must default to a boolean value (true or false). That means that the statement '"hello"' is not a boolean value. However, \[column]="hello" is a boolean value because it is either true or false for a given row.
Concatenates two or more string values into a single string with a custom separator/delimiter. Combines multiple text values in the order they are provided. Returns an empty string if all input values are null.
Converts a value to a decimal column type. Handles conversion from strings, integers, and other numeric types.
Converts a value to an integer columns type. Rounds down to the nearest integer when converting from float values.
Converts a text literal or text column to a datetime type. Note that the value has to be without a time component and in this format: YYYY-MM-DD.
Converts a text literal or text column to a datetime type. Note that the value has to be with a time component and in this format: YYYY-MM-DD HH:MM:SS.
Logical operator that returns true only if all conditions are true. Typically used within IFF functions or [IF Column](/tools/new-columns/if-column) tool for complex conditional logic. Returns false if any condition is false or null.
Each part of the AND function must default to a boolean value (true or false). That means that the statement '"hello"' is not a boolean value. However, \[column]="hello" is a boolean value because it is either true or false for a given row.
Logical operator that returns true if at least one condition is true. Typically used within IFF functions or [IF Column](/tools/new-columns/if-column) tool for complex conditional logic. Returns false only if all conditions are false or null.
Each part of the OR function must default to a boolean value (true or false). That means that the statement '"hello"' is not a boolean value. However, \[column]="hello" is a boolean value because it is either true or false for a given row.
Returns a boolean value indicating whether a value is null. Returns true if the value is null, false otherwise. Useful for conditional logic and data validation.
Returns a boolean value indicating whether a value is not null. Returns true if the value has any non-null content, false if the value is null. Useful for conditional logic and data validation.
Returns a boolean value indicating whether a value is true. Returns true if the value is true, false otherwise. Useful for conditional logic and data validation.
Returns a boolean value indicating whether a value is false. Returns true if the value is false, false otherwise. Useful for conditional logic and data validation.
# Operations
Source: https://docs.less.tech/canvas/syntax-operations
Rounds a number to a specified number of decimal places. Can only be used on Decimal columns or expressions that return a decimal.
Returns the leftmost n characters of a string. Can only be used on String columns or expressions that return a string.
Returns the rightmost n characters of a string. Can only be used on String columns or expressions that return a string.
Returns the substring of a string. Can only be used on String columns or expressions that return a string. A substring is a range of characters within a string.
Returns the length of a string. Can only be used on String columns or expressions that return a string.
Adds or subtracts a number of days, weeks, months, etc to a datetime column. Can only be used on Datetime columns or expressions that return a date. The 'units' must be an integer. The unit can be:
1. 'seconds'
2. 'minutes'
3. 'hours'
4. 'days'
5. 'weeks'
6. 'months'
7. 'years'
Get the difference in duration between two datetime columns or expressions that return a date. Can only be used on Datetime columns or expressions that return a date.
The 'units' must be an integer. The unit can be:
1. 'seconds'
2. 'minutes'
3. 'hours'
4. 'days'
5. 'weeks'
Truncates a datetime column to a specified interval. Can only be used on Datetime columns or expressions that return a date. An example could be truncating to years which for 2025-08-01 would return 2025-01-01.
Returns the UPPERCASE of a string. Can only be used on String columns or expressions that return a string.
Returns the LOWERCASE of a string. Can only be used on String columns or expressions that return a string.
Returns the title case of a string. Can only be used on String columns or expressions that return a string.
Checks if a string literal exists in a string column or expression that returns a string. Returns a boolean (true or false).
This function is case-sensitive.
Checks if a string literal does **not** exist in a string column or expression that returns a string. Returns a boolean (true or false).
This function is case-sensitive.
# Introduction
Source: https://docs.less.tech/canvas/syntax-quickstart
Supercharge your tool configuration
Syntax is a combination of a couple of different things: constants, operations, functions, parameters and column referencing. It can be be used to chain transformations inside a number of different tools. It generally helps reduce the number of tools you need to use.
All syntax functions and operations are also available as standalone tools in the Canvas.
Syntaxing enables you to do cool things like the following:
Here we do a number of things:
1. We have an IFF function that wraps a number of other statements.
2. For the *when* part of the IFF function, we first transform the *date\_string2* column to a datetime format using the DATETIME function
3. Still in the *when* part, we add the a number of days to our transformed *date\_string2* column using the DATEMATH operation and the *int\_col* column (we add the value of the *int\_col* column as days to the *date\_string2* column)
4. We then compare it to a TODAY constant
5. If it's greater than today, then we return the "WOOOOW" as a text literal (*then* part)
6. If it's not greater than today, we return the value of the textParam parameter - "this is cool" (*else* part)
### Where can I use Syntax?
You can use syntax in a number of different tools. Note that some tools only support parameters and/or column referencing. The most common tools for Syntax is the [New Column](/tools/new-columns/new-column), [IF Column](/tools/new-columns/if-column) and [Filter](/tools/basics/filter) tools. These are all the supported tools:
* [Directory](/tools/basics/directory): only Parameters in the "table name pattern" field
* [Save](/tools/basics/save-table): only Parameters in the "table name" field
* [Filter](/tools/basics/filter)
* [Replace](/tools/basics/replace): in the "value" field
* [Add Business Days](/tools/basics/save-table): only column references in the "column name" field
* [Date Math](/tools/new-columns/date-math): in the "number of units" field
* [IF Column](/tools/new-columns/if-column)
* [New Column](/tools/new-columns/new-column)
* [Row ID](/tools/new-columns/row-id): only column references in the "column name" field
* [API](/tools/utilities/api): only to reference columns in the "URL" and "body" fields
* [Validate](/tools/utilities/validate): only in the "message" field
### What's the difference between functions, operators and constants?
[Functions](/canvas/syntax-functions) are used around a column, a literal, a parameter or other expressions. They look like this: `FUNCTION(column/literal/parameter/expression)`.
[Operations](/canvas/syntax-operations) on the other hand are "attached" to a column, a literal, a parameter or other expressions. They look like this: `column/literal/parameter/expression.OPERATOR(someConfig)`. Notice the dot between the expression and the operator.
Lastly, [Constants](/canvas/syntax-constants) are used to represent a fixed value. They look like this: `TODAY` or `NULL`.
# Email Destinations
Source: https://docs.less.tech/destinations/emails
There are a couple of email destination whcih all share the same configuration on the Canvas. Looks like this:
### Test mode and Live mode
At the top of the form you choose **Test** or **Live**:
* **Test** (default): Real addresses from your data are **not** used as recipients. Enter a **test email address**; when the tool runs, a single preview is sent **only** to that address. The subject line is prefixed with `(TEST)` where applicable. The Canvas still shows an info message summarizing what would happen in Live mode (row counts, segment counts, columns used, and whether an attachment is included).
* **Live**: Email is delivered to the recipients defined by your sending method (column values or typed addresses). The test address field is hidden; CC and BCC from your configuration are honored.
Use Test mode to validate subject, HTML body, attachments, and column substitutions before switching to Live.
In **Per row** and **Segmented** test mode, the preview uses the **first row** or **first segment** only—so you see one example email, not one per row or segment. **Entire dataset** test mode sends one preview that uses the **full** dataset in the body (including the data table placeholder) and attachment, but still delivers only to your test address.
### Sending method
Pick how you can . The rest of the form appears after you choose a method.
#### Per row
One email **per data row** (100 rows → up to 100 sends, rows with no valid recipients may be skipped).
* **To**: Choose the column whose cells hold recipient addresses. Each cell may be one address or a comma-separated list.
* **CC / BCC** (optional): Same rules, each as an optional column.
* **Subject**: Syntax-aware; you can reference **any** column from the row. Use double quotes around literal text where the editor expects it.
* **Email body**: HTML editor with column and parameter references. You can insert the **DataTable** snippet: a small inline table (first **20** rows × **10** columns of non-recipient columns) substituted into the message.
* **Attachment** (optional): **CSV** or **Excel (.xlsx)**. Each attachment contains **that row’s** data (recipient columns are omitted from the file).
Typical use: many recipients, each with a small personalized message or row-level attachment.
#### Entire dataset
Typically **one** email for the whole run.
* **To**: Type addresses directly (one or comma-separated). **CC** and **BCC** are optional free-text fields with the same format.
* **Subject** and **body**: Plain configuration for that single send—**no** per-row column references in the subject (the dataset is one blob). The body still supports parameters, the **DataTable** placeholder, and HTML.
* **Attachment**: The **full** dataset as CSV or XLSX when selected.
Typical use: scheduled reports to a fixed distribution list.
#### Segmented (advanced)
One email per **segment**, where a segment is each **distinct combination** of the columns you select under **Segment data and recipients**.
* **Segment columns**: Multi-select. Values from these columns are constant within a segment, and only these columns are available in the **subject** syntax picker (plus literals).
* **To / CC / BCC**: Column-based, like Per row. Within each segment, **all unique** addresses found in that segment’s rows for the To column receive **one** shared email (and similarly for CC/BCC).
* **Body**: You can reference segment columns, parameters, and **DataTable**; the table and attachment reflect **that segment’s** rows only.
Typical use: different teams or regions each get one tailored message and their slice of the data.
### Attachment filename
If you choose CSV or Excel, you can optionally set **Attachment filename** with the same syntax rules as the subject where column references are allowed (per mode). If you omit it, a sensible default name is used.
### Limits and validation
* The email body must contain enough visible text after HTML is stripped (minimum length is enforced in the form).
* Large attachments are capped (very large exports may require fewer rows/columns upstream or CSV instead of Excel). If a run hits provider message-size limits, reduce data or drop the attachment.
# MySQL
Source: https://docs.less.tech/destinations/guides/MySQL
You need to make sure the Less IPs are whitelisted from your MySQL database. You can find the IPs [here](/guides/less-ip).
You need to have a user account with write access to the database to be able to use the MySQL destination.
### Setup
For most MySQL databases, you can use the default connection method. However, if you are using a database that requires SSH, you can use the SSH connection method.
Most MySQL databases are supported.
To connect to a MySQL database, the easiest is to find your connection string. This is usually found in the database's settings (alternatively, ask your database admin for a connection string). It looks something like this:
```
mysql://myuser:mypassword123@db.example.com:3306/company_db
```
Which maps to the following:
```
mysql://:@:/
```
Save those values for the steps below.
The first step is input **host**, **port** (almost always 3306), and the name of the **database** you want to extract data from.
Input your **username** and **password** from the connection string you found above.
We recommend trying without SSH first if you're in doubt. If you are using a database that requires SSH, you can use the SSH connection method.
Input your **SSH host**, **SSH port**, **SSH username**, and **SSH password** from the database's settings.
You can also choose to use a private key instead of a password. Just check the "I want to use an SSH Key" checkbox and upload your private key file.
Once you have input your account and credential information, you need to validate your connection. Click "Test Connection" to confirm that we can connect to the database. Note that we **do not** change error message coming from the database.
# BigQuery
Source: https://docs.less.tech/destinations/guides/bigquery
The BigQuery destination writes canvas output to a table in Google BigQuery.
### Authentication
Less connects to BigQuery with a **Google Cloud service account JSON key**. This is the recommended approach for automated load jobs.
**OAuth (sign in with Google) is not supported yet** for BigQuery. Other Google connectors in Less (such as Google Sheets) use OAuth, but the BigQuery source and destination currently require a service account.
See [How to create a BigQuery service account](/sources/guides/bigquery-service-account) for step-by-step instructions.
### Setup
Enter your Google Cloud **project ID**. Optionally set a default **dataset** so canvas nodes can use short table names, and a **location** if your load jobs run in a specific region.
Upload your **service account JSON key file**. The service account needs **BigQuery Data Editor** on the destination dataset and **BigQuery Job User** at project level so Less can run load jobs.
See [How to create a BigQuery service account](/sources/guides/bigquery-service-account) if you need help creating the key.
Click **Connect** to verify the credentials and permissions before saving the destination.
On the canvas, set the output table name as `dataset.table`, or `project.dataset.table` when you need to override the configured project or dataset. Supported operations are **overwrite** and **append**.
# ClickHouse
Source: https://docs.less.tech/destinations/guides/clickhouse
You need to make sure the Less IPs are whitelisted from your ClickHouse database. You can find the IPs [here](/guides/less-ip).
You need to have a user account with write access to the database to be able to use the ClickHouse destination.
### Setup
To connect to a ClickHouse database, the easiest is to find your connection string. You can find this by Clicking "Connect" in your Clickhouse environment. Then download the connection string. It should look something like this:
```
defaulthostname84431defaultpassword
```
Save those values for the steps below.
The first step is input **server address**, **port** (almost always 8443), and the name of the **database** you want to extract data from.
Input your **username** and **password** from the connection string you found above.
We recommend trying without SSH first if you're in doubt. If you are using a database that requires SSH, you can use the SSH connection method.
Input your **SSH host**, **SSH port**, **SSH username**, and **SSH password** from the database's settings.
You can also choose to use a private key instead of a password. Just check the "I want to use an SSH Key" checkbox and upload your private key file.
Once you have input your account and credential information, you need to validate your connection. Click "Test Connection" to confirm that we can connect to the database. Note that we **do not** change error message coming from the database.
# Google Sheets
Source: https://docs.less.tech/destinations/guides/googlesheet
You can view an how to set up and use the Google Sheet destination in our video guide below:
### Setup
You need to complete two steps before you can start sending data to your Google Sheets.
The first step is to authenticate with Google. You can do this by clicking the "Authenticate with Google" button.
Once you have authenticated, you will be redirected back to Less.
On the Spreadsheets tab, click the "Open Google File Picker" button. We unfortunately have to use Google's own methodology for choosing which spreadsheets to send data to.
You can select multiple spreadsheets as long as your in the same directory/folder.
Navigate to the Canvas and input a Destination tool whereever you'd like to send data to your Google Sheets. Choose that Google Sheet destination, choose the relevant spreadsheet and input the sheet name and range you'd like to send data to.
# Mailchimp Transactional Emails
Source: https://docs.less.tech/destinations/guides/mailchimp
The Mailchimp destination sends emails using **Mandrill** (Mailchimp Transactional API). All recipient and content information comes from your incoming data—no Mailchimp list or audience is used. You can send one email per row or one email per group when using Group By.
You need a **Mandrill API key** from Mailchimp: Account & Billing → Extras → Mandrill. This is separate from the Marketing API key. Verify your sending domain in Mandrill so emails can be delivered.
### Setup
Create a Mailchimp destination and complete the **Credentials** step:
* **Mandrill API key** (required): Your Mandrill API key from Mailchimp.
* **From email**: Sender address for outgoing emails. Must be a verified domain in Mandrill. Defaults to [noreply@less.tech](mailto:noreply@less.tech) if empty.
* **From name**: Display name for the sender.
### On the Canvas
Check this [guide](/destinations/emails) to see how to use emails destinations on the Canvas.
# Microsoft SQL Server
Source: https://docs.less.tech/destinations/guides/mssql
Allow inbound access from [Less IP addresses](/guides/less-ip) to your SQL Server instance (firewall, Azure SQL networking rules, security groups, and so on).
The login you use must have permission to **create and write** in the target database so Less can load data from models.
The Microsoft SQL Server destination writes data from Less into SQL Server, **Azure SQL** (including Azure SQL Database), or **Microsoft Fabric SQL Database**. The wizard asks for a TCP connection: host, port, database, and credentials.
The default port is **1433** unless your administrator assigns a different one.
Enter the **host** (hostname or IP, for example `db-test.mssql.database.azure.com` for Azure SQL or `*.database.fabric.microsoft.com` for Fabric SQL Database), **port** (typically **1433**), and the **database** name.
Select your **authentication type**:
* **SQL username and password** (default) — enter the **username** and **password** for SQL authentication (for example a contained database user on Azure SQL or a SQL login on your instance).
* **Microsoft Entra Service Principal** — enter the **client ID** and **client secret** from a Microsoft Entra app registration. Required for Fabric SQL Database and other Entra-only endpoints. See [How to create Entra Service Principal](/sources/guides/mssql-entra-service-principal).
If the database is only reachable through a jump host, enable the SSH tunnel and provide **SSH host**, **port**, **username**, and **password**, or use an **SSH key** instead of a password.
If your server is directly reachable from the internet or a private link Less can use, you can leave the tunnel disabled.
Use **Test Connection** to verify host, port, database, and credentials before saving. Error messages are returned as received from SQL Server.
# PostgreSQL
Source: https://docs.less.tech/destinations/guides/postgresql
You need to make sure the Less IPs are whitelisted from your MySQL database. You can find the IPs [here](/guides/less-ip).
You need to have a user account with write access to the database to be able to use the PostgreSQL destination.
### Setup
For most PostgreSQL databases, you can use the default connection method. However, if you are using a database that requires SSH, you can use the SSH connection method.
Neon, Supabase, PlanetScale, Aurora,Redshift, and other PostgreSQL-compatible databases are supported. Basically, any PostgreSQL database is supported.
To connect to a PostgreSQL database, the easiest is to find your connection string. This is usually found in the database's settings (alternatively, ask your database admin for a connection string). It looks something like this:
```
postgresql://myuser:mypassword123@db.example.com:5432
```
Which maps to the following:
```
postgresql://:@:/
```
Save those values for the steps below.
The first step is input **host**, **port** (almost always 5432), and the name of the **database** you want to extract data from.
Input your **username** and **password** from the connection string you found above.
We recommend trying without SSH first if you're in doubt. If you are using a database that requires SSH, you can use the SSH connection method.
Input your **SSH host**, **SSH port**, **SSH username**, and **SSH password** from the database's settings.
You can also choose to use a private key instead of a password. Just check the "I want to use an SSH Key" checkbox and upload your private key file.
Once you have input your account and credential information, you need to validate your connection. Click "Test Connection" to confirm that we can connect to the database. Note that we **do not** change error message coming from the database.
# Amazon Redshift
Source: https://docs.less.tech/destinations/guides/redshift
Allow inbound access from [Less IP addresses](/guides/less-ip) to your Redshift cluster (for example via the cluster security group and any network path in front of it).
The database user you configure must have permission to **create and write** objects Less needs when pushing data from models into Redshift.
The Amazon Redshift destination writes data from Less into your Redshift cluster. You supply the cluster endpoint, database credentials, and optionally **S3 bulk loading** for better throughput on large loads.
Redshift listens on port **5439** by default (not 5432).
Enter the **host** (for example `my-cluster.xxxxxx.region.redshift.amazonaws.com`), **port** (typically **5439**), and the **database** name Less should connect to.
Provide the Redshift **username** and **password** for that database.
Leave **Use S3 bulk loading** off for simple setups; Less will still connect over SQL.
When bulk loading is **enabled**, Less stages files in S3 and loads them with Redshift **COPY**. You must then supply:
* **AWS Access Key ID** and **AWS Secret Access Key** for an identity that can write to the staging bucket
* **S3 Staging URI** (for example `s3://my-bucket/redshift-staging/`) — the bucket should be in the **same AWS Region** as your Redshift cluster
If bulk load is off, the AWS and S3 fields are not required.
Try without SSH first unless your network requires a bastion. To use a tunnel, enable it and enter **SSH host**, **port**, **username**, and **password**, or enable **SSH key** and upload your private key.
Run **Test Connection** to confirm Less can reach Redshift. Error messages are passed through from the database.
# Resend
Source: https://docs.less.tech/destinations/guides/resendemail
The Resend destination sends transactional emails using the **Resend API**. All recipient and content information comes from your incoming data. You can send one email per row or one email per group when using Group By.
You need a **Resend API key** from [resend.com/api-keys](https://resend.com/api-keys). Make sure to verify your sending domain in Resend so emails can be delivered.
### Setup
Create a Resend destination and complete the **Credentials** step:
* **Resend API key** (required): Your API key from Resend (starts with `re_`).
* **From email**: Sender address for outgoing emails. Must be from a verified domain in Resend. Defaults to [noreply@less.tech](mailto:noreply@less.tech) if empty.
* **From name**: Display name for the sender.
### On the Canvas
Check this [guide](/destinations/emails) to see how to use emails destinations on the Canvas.
# Sharepoint
Source: https://docs.less.tech/destinations/guides/sharepoint
You can view an how to set up and use the Sharepoint destination in our video guide below:
### Setup
You need to complete two steps before you can start sending data to your Google Sheets.
The first step is to authenticate with Google. You can do this by clicking the "Authenticate with Microsoft" button.
Once you have authenticated, you will be redirected back to Less.
Select where you want to be able to write files to. You can select multiple folders.
Navigate to the Canvas and input a Destination tool whereever you'd like to send data to your Google Sheets. Choose that Google Sheet destination, choose the relevant spreadsheet and input the sheet name and range you'd like to send data to.
# Snowflake
Source: https://docs.less.tech/destinations/guides/snowflake
You need to make sure the Less IPs are whitelisted in your Snowflake account. You can find the IPs [here](/guides/less-ip).
You can also choose to use PAT (programmatic access tokens) instead of username and password. You need to have a user account with write access to the database to be able to use the Snowflake destination.
You can find most of the information you need from Snowflake here. You also need a compute warehouse which you can find under Compute in the left sidebar of Snowflake. Lastly, you need the name of database you want to extract data from.
### Password or Service Account Setup
There are two parts to setting up a Snowflake destination.
The first step is input **account identifier**, **compute warehouse**, and the name of the **database** you want to send data into.
Step two is to input a **role** (see the GIF above to find it in Snowflake). Secondly, you need to select your **authentication type**. By default, you can only choose "Password". You can enable OAuth 2.0 authentication as well (see below).
Input your **username** and **password** if you choose "Password" authentication. Alternatively, click "Authenticate with Snowflake" if you have enabled OAuth 2.0 authentication.
We're working on enabling Service Account authentication
Finally, we recommend that you test the connection before continuing to ensure that the connection is successful.
### OAuth 2.0 Authentication
Admins and Super Admins can enable the users in your Less workspace to connect to Snowflake with OAuth 2.0 authentication. To do so, you need to first create a custom OAuth 2.0 application in Snowflake. You can find the instructions [here](https://docs.snowflake.com/en/user-guide/oauth-custom).
This is rather complex. Reach out to us if you want our help with setting up Snowflake OAuth 2.0 authentication.
Once you've created the OAuth 2.0 application in Snowflake, navigate Settings -> Other and click "Connect" in the Snowflake OAuth settings section. There you'll need to input the following:
* **Client ID**: The Client ID of the OAuth 2.0 application you created in Snowflake.
* **Client Secret**: The Client Secret of the OAuth 2.0 application you created in Snowflake.
* **Authorization URL**: The Authorization URL of the OAuth 2.0 application you created in Snowflake.
* **Token URL**: The Token URL of the OAuth 2.0 application you created in Snowflake.
Click "Save Settings" to continue.
Once you've saved the OAuth 2.0 application, you can now connect to Snowflake with OAuth 2.0 authentication when setting up a Snowflake source.
# Quickstart
Source: https://docs.less.tech/destinations/quickstart
Use Destination to send data elsewhere
When creating a new destination, you need to always need to input a **name** and **description**. The rest of the input differs depending on the destination you're creating. You can view more by going into the specific guide for the destination you're creating.
You can view an example of how to set up and use a destination in our video guide below:
# Browse
Source: https://docs.less.tech/essentials/browse
Inspect data
On the Browse page you can see all the tables that are either coming into Less from a source or from using the [Save Table](/tools/basics/save-table) tool. This is like a central hub for all your data.
You can also view the tables for the sources and models that you have [permission](/guides/permissions-quickstart) to read.
### Overview
From the overview you can do the following actions:
1. Search for a table by name
2. Create a new tag
3. See all your tables including its status, tag, what generated it, when it was last updated and the rows and columns in the table
4. Filter the tables by status, owner, generation type (source or model), source name and tags
You can click on a table to view more details in the right-hand side panel.
### Tags and Statuses
You can add **tags** to tables to help you organize your data. That could for example be by department such as sales, marketing, finance, etc. Or if you a consultancy, you could tag tables by client.
You can view all your tags by navigating to the Profile page and clicking on the *Tags* tab. Here you can also create new tags.
**Statuses** on the other hand are defined by us and are used to indicate the health of a table. You can choose between "No Status", "Raw", "Deprecated", "Draft", "Verified". It's entirely up to you if we want to use our statuses but it can help your colleagues understand which tables are ready to use and which are not.
### Single table view
When selecting a single table you can see more details about the table. You can change it's status (1), add tags (6), and edit the table description (5).
You'll also see what it's generated by, when it was last updated, the owner and the number of rows and columns in the table (7).
We number 2, 3 and 4 in the image above you can view the first 100 rows of the table (2), view the schema, i.e. the columns, their type, min/max values and a null count (4) and delete the table (5).
Note that if you delete a table that is created by a source/model which is on a schedule, the table will be created again the next time the source/model runs
### Multiple table view
When you select multiple tables you'll see each tables, its description and status. You can hover a table and click "x" to select it. Press "escape" to deselect all tables. You can use the action bar at the bottom of the screen to add tags and delete multiple tables at once.
# Credits
Source: https://docs.less.tech/essentials/credits
How billing works
Credits are spent in two ways: when working on the Canvas and when jobs run. On Less, you can choose how much power you want to use for sessions and for jobs. The more power you use, the more credits you spend.
### Instances and Credit usage
You spend credits faster on larger instances. On a Micro instance, you will use 0.1 credits per hour. On a X-Large instance, you will use 8 credits per hour.
A couple of examples:
1. You use a Micro instances for 10 hours on the Canvas. You will use 10 \* 0.1 credits = 1 credit
2. You use a X-Large instance for 26 minutes on the canvas. You will use 26/60 \* 8 credits = 3.46 credits
3. You have a source that updates every hour. It runs for 4 minutes on a Medium instance. You will use 4/60 \* 2 credits = 0.13 credits for each job and 0.1333 \* 24 = 3.2 credits for the day (i.e. 24 jobs)
4. You have an orchestration that runs once per day. The orchestration runs for 7 minutes and activates 2 jobs:
1. Job 1 runs for 3 minutes on a Medium instance. You will use 3/60 \* 2 credits = 0.1 credits
2. Job 2 runs for 4 minutes on a Small instance. You will use 4/60 \* 1 credits = 0.06 credits
3. Your orchestration job runs for 7 minutes on a Micro instance. You will use 7/60 \* 0.1 credits = 0.01 credits
4. You will use 0.1 + 0.06 + 0.01 = 0.17 credits per run
### Canvas
When you open new model, we create a session for you. You can see which session you're using next to the title. You can track how much power you're utilising of that instance with the metrics (see below).
Read more about instances and credit usage on the canvas [here](/canvas/instaces).
### Jobs
When you schedule a source, model or orchestration to run, it becomes a job. Every time it runs, it uses credits. You can choose which instance to use for your job when editing a source or a model. Orchestrations always use a micro instance to run (obviously the individual jobs use their own specified instances - think of the orchestration as a "background"/meta job).
# Destinations
Source: https://docs.less.tech/essentials/destinations
Activate data
Destinations helps you activate the data created by models. A destination is a way to send the data to another system, database, spreadsheet or even emails.
You can read more about setting up each destination [here](/destinations/quickstart).
Reach out to us if you want us to build a new destination for you.
The really smart thing about destinations is that they're reusable. You can set up your Snowflake destination once and then use it for all your models. You can even share your Snowflake destination with others so they can use it too.
You can view an example of how to set up and use a destination in our video guide below:
# Models
Source: https://docs.less.tech/essentials/models
Analyze data
Models helps you transform the raw data extracted from sources to clean and useful tables providing insights. Typically, Less users use the tables created by models in visualisations tools, to send emails or to automate tasks like updating a CRM system.
You can use the output of one model as the input to another model. That is generally considered best practice so you don't end up with huge and overwhelming models. Use an [orchestration](/essentials/orchestration) to run models (and sources for that matter) in the right order.
Models are built on the Canvas - you can read much more about that [here](/canvas/quickstart). We also recommend checking out our [Academy](/academy/introduction) to get started building models.
You can create new models by navigating to a folder and clicking the *Create* button in the top-right corner.
### Schedule a model to run automatically
You can schedule a model to run whenever you want. The first thing you have to ensure is that the model has a [published version](/canvas/draft-publish).
Then navigate to the folder with the model and click on the three dots to the right-hand side.
You'll see three options: 1) never to avoid scheduling, 2) basic or 3) cron.
If you choose **basic**, you can select the interval (hourly, daily or weekly), the time of day, the timezone and the day of the week (only for weekly).
If you choose **cron**, you get full control over the schedule. Cron syntax is a powerful way to schedule your model runs. It consists of five fields:
* Minute
* Hour
* Day of month
* Month
* Day of week
For example, `0 0 * * *` would run the model every day at midnight. Where 0 in minute means at the start of the hour and 0 in hour means at the start of the day (i.e. midnight). \* means every minute, every hour, every day, every month, every day of the week so in this case every day of every month at midnight.
You could also choose to input `15 8-17/4 * * 1-5` to run your model at 15 minutes past the hour, every 4 hours, between 08:00 AM and 05:59 PM, Monday through Friday. In sum, you have full control.
You can choose from one of our presets and you can also view the 10 next times the model will run given your cron expression.
# Orchestrate
Source: https://docs.less.tech/essentials/orchestrate
Run models and sources in sequence
The orchestrate functionality helps you run models and sources in a specific sequence. This is useful if you want to run a model after a source has been run or if you want to run a model after another model has been run.
We recommend switching off individual schedules for models and sources when using an orchestrate to avoid double runs.
You can create new orchestrates by navigating to a folder and clicking the *Create* button in the top-right corner.
You can add as many models and sources that you want. The sources/models run in the order from the top to the bottom. You can delete and reorder the order with the buttons to the right.
You can also choose if you **want to continue running the orchestrate if a model or source fails**. Simple check the box and the orchestrate will continue running the next models and sources without stopping.
# Sources
Source: https://docs.less.tech/essentials/sources
Get data
Sources is the place to begin when using Less. They help you extract data from systems, files and databases into Less. You can read more about setting up Sources [here](/sources/quickstart).
If its technically feasible we build new sources for free. Just
reach out to us and we'll get back to you as soon as possible.
You can create new Sources by navigating to a folder and clicking the *Create* button in the top-right corner.
# Inviting Team Members
Source: https://docs.less.tech/guides/inviting-teammembers
Only Admins and Super Admins can invite team members to join your workspace. They can do that by navigating to the Settings page.
You can choose if a new user should be an Admin, Super Admin or a Creator. Admins can access and edit all tabs in the Settings page. Super Admins can create new Admins. Creators are not able to create or edit any thing on the platform. Disabling the Creator functionality is built for things like auditors and equivalent.
All users can see a list of all users in the workspace. The list is avaliable through the Profile page.
# Less IP
Source: https://docs.less.tech/guides/less-ip
If you set up a [Destination](/destinations/quickstart) or [Source](/sources/quickstart) you might need to whitelist the Less IP address below. Whitelisting means that you allow Less to access your systems. This is particularly relevant for databases.
Feel free to reach out to support if you need help.
```json IPs theme={null}
3.71.252.51
3.67.107.235
18.199.206.56
```
If you're on an Enterprise tier, you can have dedicated IPs.
# Logs
Source: https://docs.less.tech/guides/logs
Monitor your scheduled assets with logs
There are a number of ways in which you can monitor your scheduled assets on Less. The simplest is from the Home page ranging to building your own custom monitoring with the Log Connector.
### Home
From the Home page, you can easily view the successes, failures and warnings for your scheduled assets.
You can click on the graph to view the given assets in the table below. You can adjust filters at the top of the page.
### Asset Specific Logs
You can also access asset specific logs from the folders. From there you can see summary statistics for the given asset as well as a detailed log for each job.
This is an excellent place to debug if you have issues running your asset!
You can see things like duration, highest CPU and highest memory for each job. The latter two could be relevant to understand if you could use a smaller instance.
For the detailed log, you can search in the message field or you can filter by the various fields - such as the duration of each event.
### Log as a Table
If you want to create your own custom monitoring - in a dashboard for example - you can use the [Log Source](/connectors/guides/less-logs). A Log Connector extract everything you can find in the Detailed Logs into separate tables. You can send those tables to a database using a Destination.
# Notifications
Source: https://docs.less.tech/guides/notifications
Get email alerts
You can choose to subscribe to notifications for models and source.
The first step is to enable notifications for a given model, source or orchestration. You can do that by navigating to a folder page and clicking on the "bell" icon on the given row.
The second step is navigating to the Profile page and clicking on the "Notifications" tab.
First of all enable email notifications. Then select if you want to be notified when an asset fails, succeeds or creates a warning.
# Abilities
Source: https://docs.less.tech/guides/permissions-abilities
An ability enables you to do something on Less
There are quite a bit of abilities available in Less, and to help you understand them, here's a short description of each ability. We bundle these into default [roles](/guides/permissions-roles) but platform Admins can also create your own customized roles.
# Groups
Source: https://docs.less.tech/guides/permissions-groups
Collections of users
Groups are collections of users. A [role](/guides/permissions-roles) is given to a group on an asset which gives the users in the group certain [abilities](/guides/permissions-abilities). We provide three default roles: Managers, Editors and Viewers.
You can find all the groups in your workspace by navigating to your Profile and clicking on Groups.
Here you can view all members of each group and creat new groups. If you have the right permissions, you can also also rename the group, add/remove members and delete the group.
# Quickstart
Source: https://docs.less.tech/guides/permissions-quickstart
Get started with permissions in Less
You want to share your work with your colleagues. Great! You've come to the right place.
We provide three groups - Managers, Editors and Viewers - and three roles out-of-the-box - Manager, Editor and Viewer. You can make your own if you want. But we typically recommend sticking with the defaults in the beginning.
You can only set permissions on Folders. This grants a [group](/guides/permissions-groups.mdx) certain [abilities](/guides/permissions-abilities) on the assets within that folder.
### How to share work
* Create a folder in the root of your workspace and give it a name you like
* Move the sources, models, destinations and orchestration you want to share into folder
* Go to the Groups tab on the Profile page (bottom left corner -> Profile -> Groups)
* Put the users you want to share the work with into the appropriate groups - or create new groups if you need to
* Give the groups the appropriate role on the folder - groups with users that should be able to delete and set permissions should be Managers, groups with people that should be able to create build and edit stuff should be Editors, groups with people that should be able to view and consume the work/tables should be Viewers
# Roles
Source: https://docs.less.tech/guides/permissions-roles
Bundles of abilities
Roles are bundles of abilities. A [group](/guides/permissions-groups) is given a role on an asset which gives the users in the group certain [abilities](/guides/permissions-abilities). We provide some default roles, but platform Admins can create their own customized roles in the [Settings](/admin/roles) page. That means you can cherry-pick the abilities you want to give to your roles.
We provide three default roles: Manager, Editor and Viewer.
**Managers** are easy - they have all the abilities. **Editors** can generally do everything except deleting and moving assets as well as managing permissions on Folders. **Viewers** are quite limited - they can only view assets. Note that **viewers** also have the ability to Read tables whereby they can load data from the assets (sources and models) that they have Read access to. You can compare them below.
# Setting permissions
Source: https://docs.less.tech/guides/permissions-setting
View and create permissions on assets
A couple of important things to know:
1. When you create a new asset in the root folder, it will be private by default. This means that only you can see and manage it.
2. If you move an asset into a folder, it will inherit the permissions of the folder.
3. If you create a new asset in a folder, it will inherit the permissions of the folder.
4. You can set individual permissions on a nested folder in a folder that overrides the parent folder's permissions.
***
You can very easily view your own permissions on an asset by hovering the shield icon of the asset.
***
To set new permissions, click on the tree dots on the given Folder row and click "Permissions". Here you can view the Groups that have permissions set on the folderand the Roles that have been assigned to them. You can also see their implicit abilities.
To set a new permission, click on the "+ Add permission set". Then select the Group you want to add and the Role you want to assign to them. Then click "Add permission set".
# Permissions deep dive
Source: https://docs.less.tech/guides/permissions-understanding
Deep dive on how permissions work in Less
Our permissions structure has **5 key components** that work together:
* **Users** → People in your workspace
* **Groups** → Collections of users (like departments)
* **Assets** → Things to protect (folders, sources, models)
* **Abilities** → Specific actions like deleting a model, uploading a source, etc.
* **Roles** → Ability bundles (we provide some default roles, but you can create your own)
**The flow is simple:** Users are added to a group, then the group is assigned a role on a folder which grants the users in the group certain abilities for the assets within that folder.
### 'Why on earth did you make it so complicated?'
You're right, it can seem a bit complicated. But it is also a bit of a pain to manage permissions if you don't have a good structure.
First of all, we don't subscribe to the idea that its smart to assign permissions to individual users. Its much easier to assign permissions to groups of users. When a new user joins or leaves, you simply add or remove them from the group. Job done. The alternative involves manually setting permissions for each user individually on each asset, which is a pain.
Secondly, Less is a data tool whereby we have to provide a great deal of control and flexibility to our users. Most software tools have roles like Viewer and Editor. However, in our case there are more nuances to account for. For example, running and publishing a models are two very different things - should they be bundled together or not in a "Editor" role? We don't think so. That's why we have the customisable roles and abilities.
Thirdly, setting abilities individually would be a nightmare. As of writing this, we have 36 abilities. It would be horrible to have to set each one individually. That's why we abstract it away into a bundle of abilities - a role.
Lastly, why can you only set permissions on folders? Because this too would great a spaghetti mess of permissions where certain assets have custom permission in a folder but not all. It would make very opaque to understand who has access to what.
### Real-world example
Let's say you have sensitive Finance data that only Finance Managers should access:
1. Create a group called "Finance Managers"
2. Create a folder - "Sensitive Finance Data" and move all the assets generating sensitive data into the folder
3. Give the "Finance Managers" group "Manager" role on the "Sensitive Finance Data" folder
4. Remove all other permission settings for the "Sensitive Finance Data" folder
5. Result: Only Finance Managers can see and manage that sensitive data
The Finance Managers group now has full control over the Sensitive Finance Data folder, while everyone else can't even see it exists.
# Versions
Source: https://docs.less.tech/guides/versions
Automatic version control
Less automatically stores all the previous versions of your models. In other words, every time a team member saves a model, a new version of that model is created automatically.
Read more about versions here: [Versions, Draft and Publish](/canvas/draft-publish)
Go to the folder with your model and click on the three dots to the right-hand side on the row. Click *Version History*.
From there you can see the currently published version (1 below) as well as the last 20 other versions (2 and 3 below).
You can click on the currently published version to open it up in a new browser window. You can also publish a different version or open it in a new browser window via the three dots on the right-hand side of each version.
If you change the published version, that version will become the scheduled model.
# Introduction
Source: https://docs.less.tech/introduction
Less enables everyone to find insights in every data source. Start solving.
Documentation
Less enables everyone to find insights in every data source. Start solving.
# Quickstart
Source: https://docs.less.tech/quickstart
Learn how to use Less in 5 minutes
Less in 11 minutes and 27 seconds
# ActiveCampaign
Source: https://docs.less.tech/sources/guides/activecampaign
This source is incremental by default. This means only new data will be extracted on each run. A full refresh of the contactTags table is triggered if more than 5.000 contacts have been created since the last run.
The ActiveCampaign source allows you to extract data from your ActiveCampaign account. You can extract Contacts, Campaign, Tags and a number of other tables.
### Setup
There are three tabs you need to configure for the ActiveCampaign source: Credentials, Date Interval and Tables.
In the Credentials tab, you need to input your ActiveCampaign API URL and key. You can find those on the Developer Settings page in your ActiveCampaign account:
1. Click "Settings" (gear icon).
2. The Account Settings menu will appear. Click the "Developer" option.
3. Copy and paste your API URL and Key into the credentials tab in the ActiveCampaign source.
In the Date Interval tab, you need to input the first/start date you want to extract data from. If you want to extract data from a fixed period, you can also input an end date.
In the Tables tab, you should simply select the tables you want to extract into Less.
# Acumatica
Source: https://docs.less.tech/sources/guides/acumatica
The Acumatica source connects to your Acumatica Cloud ERP instance and extracts the entities you select into Less.
Provide your **Acumatica base URL** (for example `https://yourcompany.acumatica.com`), **username**, **password**, and **tenant** (company name in Acumatica).
Choose the **date range** for the extraction window. Data is fetched within the range you define.
Select the **tables** you want to bring into Less.
# Airtable
Source: https://docs.less.tech/sources/guides/airtable
The Airtable source reads data from a single **base** into Less. You choose which tables (by name) to extract.
Enter your **Personal Access Token** (create one at [airtable.com/create/tokens](https://airtable.com/create/tokens)) and the **Base ID** for your base (from the base URL; it starts with `app`).
You can view it from the URL.
Add one row per **table name** you want to extract, then continue to confirm your selection.
# BigQuery
Source: https://docs.less.tech/sources/guides/bigquery
The BigQuery source lets you extract tables or custom SQL queries from Google BigQuery into Less.
### Authentication
Less connects to BigQuery with a **Google Cloud service account JSON key**. This is the recommended approach for automated extract jobs.
**OAuth (sign in with Google) is not supported yet** for BigQuery. Other Google connectors in Less (such as Google Sheets) use OAuth, but the BigQuery source and destination currently require a service account.
See [How to create a BigQuery service account](/sources/guides/bigquery-service-account) for step-by-step instructions.
### Setup
Enter your Google Cloud **project ID**. Optionally set a default **dataset** to limit table discovery, and a **location** if your queries run in a specific region (for example `US`, `EU`, or `europe-west1`).
Upload your **service account JSON key file**. The service account needs **BigQuery Data Viewer** on the datasets you want to read and **BigQuery Job User** at project level so Less can run queries.
See [How to create a BigQuery service account](/sources/guides/bigquery-service-account) if you need help creating the key.
Click **Connect** to verify the credentials and load available tables. Then either select tables from the list or switch to query-based mode and provide one or more custom SQL queries.
You can select either Table or Query-based. You cannot select both.
# How to create a BigQuery service account
Source: https://docs.less.tech/sources/guides/bigquery-service-account
Use this when setting up a [BigQuery source](/sources/guides/bigquery) or [destination](/destinations/guides/bigquery). Less connects with a **Google Cloud service account JSON key** — the standard approach for server-to-server data pipelines.
**OAuth is not supported yet** for BigQuery in Less. Google OAuth (sign in with your Google account) works for other Google connectors such as Google Sheets, but BigQuery requires a service account today. Service accounts are also what Google recommends for automated extract/load jobs.
Open the [Google Cloud Console](https://console.cloud.google.com/) and select the project that contains your BigQuery datasets, or create a new project.
Copy the **Project ID** (not the project name) — you will enter this as **Project ID** in Less.
In the Cloud Console, go to **APIs & Services** → **Library**, search for **BigQuery API**, and click **Enable** if it is not already enabled for the project.
Go to **IAM & Admin** → **Service Accounts** → **Create service account**.
Enter a name (for example `less-bigquery`) and optional description, then select **Create and continue**.
Assign roles depending on how you use Less:
* **Sources (read data)** — add **BigQuery Data Viewer** and **BigQuery Job User**.
* **Destinations (write data)** — add **BigQuery Data Editor** and **BigQuery Job User**.
You can grant roles at project level, or use dataset-level IAM for tighter access (see step 5).
Select **Continue**, then **Done**.
For least-privilege access, open **BigQuery** in the Cloud Console, select your **dataset** → **Sharing** → **Permissions** → **Add principal**.
Enter the service account email (for example `less-bigquery@my-project.iam.gserviceaccount.com`) and assign:
* **BigQuery Data Viewer** for sources
* **BigQuery Data Editor** for destinations
The service account still needs **BigQuery Job User** at project level so Less can run queries and load jobs.
Return to **IAM & Admin** → **Service Accounts**, open the service account you created, go to the **Keys** tab → **Add key** → **Create new key** → **JSON** → **Create**.
A JSON file downloads automatically. Upload that file in the **Credentials** step of the BigQuery wizard in Less.
Store the key securely. Anyone with this file can access BigQuery as the service account. Rotate or delete keys you no longer use under **Keys** in the service account settings.
In the BigQuery wizard:
1. **Account** — **Project ID**, optional default **dataset**, and optional **location** (for example `US` or `EU`).
2. **Credentials** — upload the JSON key file from step 6.
3. **Tables** (source) or **Test Connection** (destination) — click **Connect** to verify access.
BigQuery is accessed over HTTPS; you do not need to whitelist Less IP addresses for Google Cloud.
## Troubleshooting
**Invalid service account JSON**
* Upload the original `.json` key file downloaded from Google Cloud.
* The file must contain `"type": "service_account"` and a `client_email` field.
**Access Denied or permission errors**
* Confirm **BigQuery Job User** is granted at project level.
* Confirm **BigQuery Data Viewer** (source) or **BigQuery Data Editor** (destination) is granted on the dataset or project.
* If you use a default **dataset** in Less, the service account must have access to that dataset.
**Not found: Dataset or table**
* Check the **Project ID** matches the project where the dataset lives.
* Dataset and table names are case-sensitive in BigQuery.
**Location errors**
* If datasets use a regional location (for example `europe-west1`), set the same **location** in the Less Account step.
**Further reading**
* [BigQuery IAM roles](https://cloud.google.com/bigquery/docs/access-control)
* [Create and delete service account keys](https://cloud.google.com/iam/docs/keys-create-delete)
# Bridgit Bench
Source: https://docs.less.tech/sources/guides/bridgit
The Bridgit Bench source pulls workforce and resource data from Bridgit Bench into Less.
Enter your **Account ID**. Choose an **authentication method**: either a **Bearer token**, or **username** and **password** for a service account, depending on what your Bridgit administrator provides.
Select the **tables** you want to extract to Less.
# ClickHouse
Source: https://docs.less.tech/sources/guides/clickhouse
You need to make sure the Less IPs are whitelisted from your ClickHouse database. You can find the IPs [here](/guides/less-ip).
### Setup
To connect to a ClickHouse database, the easiest is to find your connection string. You can find this by Clicking "Connect" in your Clickhouse environment. Then download the connection string. It should look something like this:
```
defaulthostname84431defaultpassword
```
Save those values for the steps below.
The first step is input **server address**, **port** (almost always 8443), and the name of the **database** you want to extract data from.
Input your **username** and **password** from the connection string you found above.
We recommend trying without SSH first if you're in doubt. If you are using a database that requires SSH, you can use the SSH connection method.
Input your **SSH host**, **SSH port**, **SSH username**, and **SSH password** from the database's settings.
You can also choose to use a private key instead of a password. Just check the "I want to use an SSH Key" checkbox and upload your private key file.
Once you have input your account and credential information, you need to validate your connection on the Tables tab. Click "Connect" to continue. Note that we **do not** change error message coming from the database.
If you can successfully connect to the database, you can now select the **tables** you want to extract data from. Alternatively, you can switch to the "query-based" tab to write one or more SQL queries to extract data from the database.
You can select either Table or Query-based. You cannot select both.
# Dixa
Source: https://docs.less.tech/sources/guides/dixa
This source is incremental by default. This means that new data will be extracted on each run.
The Dixa source allows you to extract data from your Dixa account. You can extract Conversations and Messages into Less.
### Setup
There are two tabs you need to configure for the Dixa source: Credentials and Tables.
In the Credentials tab, you need to input your Dixo API token. Follow this guide to get your API token: [https://docs.dixa.io/docs/tutorial-create-an-api-token](https://docs.dixa.io/docs/tutorial-create-an-api-token).
You also need to input the first/start date you want to extract data from. If you want to extract data from a fixed period, you can also input an end date. You can find more information about the date format [here](https://docs.dixa.io/docs/date-format).
In the Tables tab, you should simply select the tables you want to extract into Less.
# Dynamics 365
Source: https://docs.less.tech/sources/guides/dynamics
This source connects to **Dynamics 365** using Microsoft Entra (Azure AD) OAuth. After authentication you configure the environment and choose which entities to extract.
Sign in with Microsoft and authorize Less. A **refresh token** is stored so runs can execute on a schedule.
Provide your Microsoft **Tenant ID**, the **Environment** to use (for example `Production` or a named sandbox), the **Company** identifier Less should query, and a **date range** for entities that support date filtering (such as ledger or invoice tables).
Select the **Dynamics 365 tables** you want to load into Less. Use the OData source to extract custom tables.
# Dynamics 365 Business Central (OData)
Source: https://docs.less.tech/sources/guides/dynamics365bc
This source reads data from **Dynamics 365 Business Central** through **OData v4** endpoints. You authenticate with Microsoft, then register one or more OData URLs as named tables in Less.
Complete Microsoft sign-in so Less can store a **refresh token** for scheduled runs.
For each dataset, paste a **Business Central OData v4 URL** and give it a **table name** Less should use. You can add multiple URL and name pairs. Microsoft’s [OData web services overview](https://learn.microsoft.com/dynamics365/business-central/dev-itpro/webservices/odata-v4) explains how to obtain valid URLs.
# ECB Exchange Rates
Source: https://docs.less.tech/sources/guides/ecb
The ECB sources is a relatively simple source that gives you the exchange rates for a given currency - the base currency is EUR. The dataset looks like this:
### Setup
In the Exchange Rates tab, you need to select the **currency** you want to extract. Then you need to select the **start date** of the period you want to extract. You can also input an **end date** if you want to extract a specific period, but you can leave it blank to extract the latest rate.
Every time the source is run, it will create a new dataset with the exchange rates for the currency and period you selected. The data is typically updated by ECB around 16:00 CET on buseinss days.
We support the following currencies:
* DKK: Danish Krone
* GBP: British Pound
* USD: US Dollar
* AUD: Australian Dollar
* CAD: Canadian Dollar
* CHF: Swiss Franc
* CNY: Chinese Yuan
* HKD: Hong Kong Dollar
* ISK: Icelandic Króna
* JPY: Japanese Yen
* KRW: Korean Won
* MYR: Malaysian Ringgit
* NOK: Norwegian Krone
* SEK: Swedish Krona
* SGD: Singapore Dollar
* CZK: Czech Koruna
* ZAR: South African Rand
* PLN: Polish Zloty
# e-conomic
Source: https://docs.less.tech/sources/guides/economic
You must either by a Superadmin or have both "Accounting" and "Sales" access to authenticate this source.
The access rights can be changed by navigating to "All settings" -> "Subscription status".
The e-conomic source is authenticated with OAuth 2.0. All you have to do is check whether you have the Dimensions (departments) add-on and then click "Authenticate with e-conomic".
The Dimensions (departments) is incluedd in the "Advanced" tier and otherwise it is an add-on.
Once you have authenticated, you can click "Next" and select the tables you want to extract.
# Files
Source: https://docs.less.tech/sources/guides/files
The Files source allows you to extract data from files stored in your file system. We support CSV, Excel and Parquet files with a maximum file size of 2GB.
### Setup
There are two parts to setting up a Files source. You first need to upload the file(s) you want to extract data from. You can upload multiple files at once but maximum 10 files per Source.
The first step is upload the file(s) you want to extract data from. Maximum file size is 2GB.
In the second step, you see each of your files as expandable items. It looks like this:
We scan each file to help you customize the extraction. We based this on the first 20 rows of the file.
For **CSV** files, you can select the **encoding**, **delimiter**, **skip rows** and **columns**. The columns are based on the suggested skipped rows - i.e. if we suggest to skip 3 rows, the columns will be the first row after the skipped rows.
For **Excel** files, you can select the **sheet** you want to extract. You can select more sheets if you want. For each sheet you can input the number of rows to skip and the columns to extract.
For **Parquet** files, you can select the **columns** to extract.
# Go4Schools
Source: https://docs.less.tech/sources/guides/go4schools
The Go4Schools source connects to your school’s Go4Schools API to extract assessment, attendance, and related data.
Enter the **API key** supplied by your school, the **academic year** to extract (for example `2026`), and optionally a **year group** if you are pulling grade-related endpoints (for example `11` or `Reception`).
Choose which **tables** to extract into Less.
# Google Ads
Source: https://docs.less.tech/sources/guides/googleads
This source is incremental by default. This means only new data will be extracted on each run.
The Google Ads source allows you to extract data from your Google Ads account. If you have a Manager Account ID, you can extract data from all accounts in that manager account.
In the Authenticate step, click "Authenticate with Google" and you'll be redirected to a Google login page. Login with your Gmail account and grant access to Less.
In the Configuration step, you need to either input a Google Ads Customer ID or a Google Ads Manager Account ID.
If you input a Manager Account ID, you can extract data from all accounts in that manager account if you "Enable" the "Get all account available to manager account" checkbox. If you choose that, you're Customer ID will be disabled.
In the Date Interval step, you need to input the first/start date you want to extract data from. If you want to extract data from a fixed period, you can also input an end date.
In the Tables step, you need to select the tables you want to extract into Less. You can select predefined tables (Video Metrics and Campaigns) or you can write your own GAQL Queries. You can build you query in the Google Query Builder [here](https://developers.google.com/google-ads/api/fields/v22/overview_query_builder).
# Google Analytics (GA4)
Source: https://docs.less.tech/sources/guides/googleanalytics
This source is incremental by default. This means only new data will be extracted on each run.
The source is only applicable to extract Google Analytics 4 data - Universal Analytics is not supported.
In the Authenticate step, click "Authenticate with Google" and you'll be redirected to a Google login page. Login with your Gmail account and grant access to Less.
In the Configuration step, you need to input your Google Analytics Property ID. You can find more information about how to find your Property ID [here](https://developers.google.com/analytics/devguides/reporting/data/v1/property-id#what_is_my_property_id).
In the Tables step, you need to select the tables you want to extract into Less. You can select predefined tables (Basic Page Overview, Source/Medium and Adwords) or you can write your own GAQL Queries. You can define your own custom dimensions and metrics. See more about that [here](https://developers.google.com/analytics/devguides/reporting/data/v1/api-schema).
# Google Sheets
Source: https://docs.less.tech/sources/guides/googlesheets
You can see a guide to setting up a Google Sheet source here:
### Setup
You need to set up a couple of things before you can start extracting data from your Google Sheets.
The first step is to authenticate with Google. You can do this by clicking the "Authenticate with Google" button.
Once you have authenticated, you will be redirected back to Less.
On the Spreadsheets tab, click the "Open Google File Picker" button. We unfortunately have to use Google's own methodology for selecting spreadsheets.
You can select multiple spreadsheets as long as your in the same directory/folder.
In the final step, you'll see each of your spreadsheets as expandable items. Once you expand an item, you can select the sheet you want to extract, the range you'd like to extract and the columns you'd like to extract. The range could for instance be "A4:B10" to skip the first 3 rows and extract the first 10 rows of the sheet in columns A and B.
# GRP Employee Info
Source: https://docs.less.tech/sources/guides/grp_employee_info
The GRP Employee Info source connects to the Dubai GRP **SOAP** employee service and loads employee records into Less.
Enter the **username** and **password** for the SOAP service. Optionally adjust **Employee status** (default `A` for active) and **Hierarchy mode** (default `D`) if your integration requires different values. Submit to create the source.
Contact your GRP administrator if you do not have service credentials or are unsure which status and hierarchy values to use.
# HiBob
Source: https://docs.less.tech/sources/guides/hibob
The HiBob source is used to extract employee data from your Bob account. We currently support extract employee, employee lifecycle and custom column/lists tables.
### Setup
There are two parts to setting up a HiBob source. You first need to create an API Service User in your Bob account. This is used to authenticate the source. You can find more information about how to create an API Service User [here](https://apidocs.hibob.com/docs/api-service-users#step-1-create-a-new-api-service-user).
The first step is input **API Service ID** and **API Service Token** from the API Service User you created.
You need to select the **tables** you want to extract.
If you select "Employee", you can choose to specify certain custom columns. That looks like this (you can only input one column per item added):
# HubSpot Sales
Source: https://docs.less.tech/sources/guides/hubspot_sales
This source is incremental by default. This means only new or updated records will be stored on each run.
The HubSpot Sales source allows you to extract CRM data from your HubSpot account into Less. You can extract Companies, Contacts, Deals, Owners, Tickets, and a number of other CRM objects.
### Setup
There are three steps to setting up a HubSpot source: Authenticate, Date Interval, and Tables.
Click **Authenticate with HubSpot** to sign in and grant Less access to your CRM data. A popup will open where you can log in to your HubSpot account and approve the requested permissions.
If your connection expires, return to this step and click **Re-authenticate** to reconnect.
Select the start date you want to extract data from. If you want to extract data from a fixed period, you can also set an end date.
Select the HubSpot objects you want to extract into Less.
Available objects include: **Companies**, **Contacts**, **Deals** (including deal stage and close date history), **Deal Pipelines**, **Owners**, **Calls**, **Emails**, **Meetings**, **Tickets**, **Products**, and **Line Items**.
For each selected object, you can optionally specify **Custom Properties** — additional HubSpot property names to include beyond the defaults. Enter them as comma-separated values or add them one at a time.
# ISO Calendar
Source: https://docs.less.tech/sources/guides/iso
The ISO Calendar is a pretty basic source that gives you every date as a row of data within an interval that you define. It can be helpful as a mapping table for other data sources.The dataset looks like this:
### Setup
The only step is input the **interval**. Here you need to input the number of years you want to look back and look forward. This is used to create the interval of dates. Every time the source is run, it will create a new dataset with the dates in the interval.
# Meta Ads
Source: https://docs.less.tech/sources/guides/metaads
This source is incremental by default. This means only new data will be extracted on each run.
Note that the Meta Ads source can take a long time to run when setup intially due to Meta API limitation. Usually, it will require running it over the course of a couple days while the API limits reset.
### Setup
To set up the Meta Ads source, first log in to with Facebook on the "Authenticate" tab.
In the "Configuration" tab, you need to input your Facebook Ad Account ID. You can find your Ad Account ID by logging in to Facebook and navigating to the "Ads Manager" page. Your Ad Account ID is the number at the end of the URL. You can also follow this guide [here](https://www.facebook.com/business/help/1492627900875762).
You also need to input the first/start date you want to extract data from. If you want to extract data from a fixed period, you can also input an end date.
In the Tables tab, you should simply select the tables you want to extract into Less.
# Motive
Source: https://docs.less.tech/sources/guides/motive
The Motive (GoMotive) source extracts fleet and telematics entities from your Motive account into Less.
Enter your **Motive API key**.
See how to create a key in Motive's [Help Center](https://helpcenter.gomotive.com/hc/en-us/articles/6177129182621-How-to-Request-an-API-Key).
Select the **Motive tables** you want to extract.
# Microsoft SQL Server (MSSQL)
Source: https://docs.less.tech/sources/guides/mssql
You need to make sure the Less IPs are whitelisted from your Microsoft SQL Server database. You can find the IPs [here](/guides/less-ip).
### Setup
For most MSSQL databases, you can use the default **SQL username and password** connection method. However, if you are using a database that requires SSH, you can use the SSH connection method.
To connect to a MSSQL database, the easiest is to find your connection string. This is usually found in the database's settings (alternatively, ask your database admin for a connection string). It looks something like this:
```
Server=myServerAddress,1433;Database=myDataBase;User Id=myUsername;Password=myPassword;
```
Save those values for the steps below.
The first step is input **server address**, **port** (almost always 1433), and the name of the **database** you want to extract data from.
Select your **authentication type**:
* **SQL username and password** (default) — use the **username** and **password** from your connection string. This works for SQL Server, Azure SQL Database with SQL authentication, and similar setups.
* **Microsoft Entra Service Principal** — use the **client ID** and **client secret** from a Microsoft Entra app registration. Required for [Microsoft Fabric SQL Database](https://learn.microsoft.com/en-us/fabric/database/sql/authentication) and other Entra-only endpoints. See [How to create Entra Service Principal](/sources/guides/mssql-entra-service-principal).
We recommend trying without SSH first if you're in doubt. If you are using a database that requires SSH, you can use the SSH connection method.
Input your **SSH host**, **SSH port**, **SSH username**, and **SSH password** from the database's settings.
You can also choose to use a private key instead of a password. Just check the "I want to use an SSH Key" checkbox and upload your private key file.
Once you have input your account and credential information, you need to validate your connection on the Tables tab. Click "Connect" to continue. Note that we **do not** change error message coming from the database.
If you can successfully connect to the database, you can now select the **tables** you want to extract data from. Alternatively, you can switch to the "query-based" tab to write one or more SQL queries to extract data from the database.
You can select either Table or Query-based. You cannot select both.
# How to create Entra Service Principal
Source: https://docs.less.tech/sources/guides/mssql-entra-service-principal
Use this when setting up a [Microsoft SQL Server source](/sources/guides/mssql) or [destination](/destinations/guides/mssql) with **Microsoft Entra service principal** authentication — required for **Microsoft Fabric SQL Database** and other endpoints that do not accept SQL logins.
In the [Microsoft Entra admin center](https://entra.microsoft.com/), go to **App registrations** → **New registration**.
Give the app a name (for example `Less connector`), leave **Redirect URI** empty, and select **Register**.
Copy the **Application (client) ID** — you will use this as **Client ID** in Less.
Open the app → **Certificates & secrets** → **New client secret**.
Add a description, choose an expiry, and select **Add**.
Copy the secret **Value** right away (it is only shown once). This is **Client secret** in Less.
In [Microsoft Fabric](https://app.fabric.microsoft.com/), open the workspace that contains your SQL database.
On the database item, open **Manage access** (or use workspace **Access**) and add your app registration.
* **Sources** — the app needs permission to **read** the database.
* **Destinations** — the app needs permission to **create and write** tables in the database.
A workspace role such as **Contributor** is usually enough; your admin may use item-level permissions instead.
In the MSSQL wizard:
1. **Account** — host, port (usually **1433**), and database name (from the database **Connection strings** in Fabric).
2. **Credentials** — choose **Microsoft Entra service principal**, then paste the **Client ID** and **Client secret** from steps 1–2.
3. **Test connection** (destination) or **Connect** on the Tables step (source).
Whitelist [Less IP addresses](/guides/less-ip) if your database uses a firewall.
## Troubleshooting
**Login timeout expired**
* Confirm the client secret has not expired.
* Check that the app was added to the correct Fabric workspace and database.
* Ensure a Fabric admin has enabled **Service principals can use Fabric APIs** under [Tenant settings](https://app.fabric.microsoft.com/admin-portal) → **Developer settings**.
* Whitelist [Less IP addresses](/guides/less-ip) on your database firewall.
**Authentication or permission errors**
* **Sources** need read access to the database; **destinations** need write access (create/insert tables).
* Re-open **Manage access** on the SQL database item and confirm the app registration is listed.
**Azure SQL (not Fabric)**
If you use Azure SQL with Entra-only auth (not Fabric), a DBA may also need to create a database user for the app:
```sql theme={null}
CREATE USER [Less connector] FROM EXTERNAL PROVIDER;
```
Grant `db_datareader` for sources and `db_datawriter` (or `db_owner`) for destinations.
**Finding host and database name**
In Fabric, open the SQL database → **Settings** → **Connection strings**. Use the **Server** value as **Host** and **Database** as **Database** in Less.
**Further reading**
* [Authentication in Fabric SQL Database](https://learn.microsoft.com/en-us/fabric/database/sql/authentication)
* [Connect to your SQL database in Fabric](https://learn.microsoft.com/en-us/fabric/database/sql/connect)
# MySQL
Source: https://docs.less.tech/sources/guides/mysql
You need to make sure the Less IPs are whitelisted from your MySQL database. You can find the IPs [here](/guides/less-ip).
### Setup
For most MySQL databases, you can use the default connection method. However, if you are using a database that requires SSH, you can use the SSH connection method.
Most MySQL databases are supported.
To connect to a MySQL database, the easiest is to find your connection string. This is usually found in the database's settings (alternatively, ask your database admin for a connection string). It looks something like this:
```
mysql://myuser:mypassword123@db.example.com:3306/company_db
```
Which maps to the following:
```
mysql://:@:/
```
Save those values for the steps below.
The first step is input **host**, **port** (almost always 3306), and the name of the **database** you want to extract data from.
Input your **username** and **password** from the connection string you found above.
We recommend trying without SSH first if you're in doubt. If you are using a database that requires SSH, you can use the SSH connection method.
Input your **SSH host**, **SSH port**, **SSH username**, and **SSH password** from the database's settings.
You can also choose to use a private key instead of a password. Just check the "I want to use an SSH Key" checkbox and upload your private key file.
Once you have input your account and credential information, you need to validate your connection on the Tables tab. Click "Connect" to continue. Note that we **do not** change error message coming from the database.
If you can successfully connect to the database, you can now select the **tables** you want to extract data from. Alternatively, you can switch to the "query-based" tab to write one or more SQL queries to extract data from the database.
You can select either Table or Query-based. You cannot select both.
# OData
Source: https://docs.less.tech/sources/guides/odata
You need to make sure the Less IPs are whitelisted in the environment your OData endpoint is hosted in. You can find the IPs [here](/guides/less-ip).
OData (Open Data Protocol) is a REST-based web protocol for querying and updating data - in Less it is used to extract data from external systems that support the protocol. It provides a standardized way to expose and consume data APIs, making it easier to integrate different systems.
Common systems that use OData include Microsoft Dynamics 365, SAP Gateway, SharePoint, and various enterprise resource planning (ERP) systems.
### Setup
There are two parts to setting up an OData source.
Start by selecting basic or NTLM (Microsoft method) authentication. Then input the **username** and **password**.
In the next tab, you can input pairs of table names and URLs. The URL is the endpoint of the OData service while the table name is the name that will be used to identify the table in Less.
You can add as many table pairs as you want - just click the "+ Add table URL" button.
# OpenApply
Source: https://docs.less.tech/sources/guides/openapply
The OpenApply source uses the **Public API** to pull admissions and related data from your school’s OpenApply site.
Enter your school’s **Base URL** (for example `https://yourschool.openapply.com`), plus the **Client ID** and **Client Secret** from OpenApply under **Settings → Integrations → Public API**.
Choose which **datasets** to extract into Less.
# Pinterest Ads
Source: https://docs.less.tech/sources/guides/pinterestads
The Pinterest Ads source uses **Pinterest OAuth** so Less can download reporting and entity data for the ad account and date range you choose.
Sign in with Pinterest.
Optionally enable **Get all accounts available to manager account** when you use a manager login. This is helpful if you're managing more subaccounts from a manager account.
If that option is off, enter your **Pinterest Ads account ID**. Then set the **date range** to choose which period you want the data to cover.
Select the **Pinterest Ads datasets** you want in Less.
# PostgreSQL
Source: https://docs.less.tech/sources/guides/postgresql
You need to make sure the Less IPs are whitelisted from your PostgreSQL database. You can find the IPs [here](/guides/less-ip).
### Setup
For most PostgreSQL databases, you can use the default connection method. However, if you are using a database that requires SSH, you can use the SSH connection method.
Neon, Supabase, PlanetScale, Aurora,Redshift, and other PostgreSQL-compatible databases are supported. Basically, any PostgreSQL database is supported.
To connect to a PostgreSQL database, the easiest is to find your connection string. This is usually found in the database's settings (alternatively, ask your database admin for a connection string). It looks something like this:
```
postgresql://myuser:mypassword123@db.example.com:5432
```
Which maps to the following:
```
postgresql://:@:/
```
Save those values for the steps below.
The first step is input **host**, **port** (almost always 5432), and the name of the **database** you want to extract data from.
Input your **username** and **password** from the connection string you found above.
We recommend trying without SSH first if you're in doubt. If you are using a database that requires SSH, you can use the SSH connection method.
Input your **SSH host**, **SSH port**, **SSH username**, and **SSH password** from the database's settings.
You can also choose to use a private key instead of a password. Just check the "I want to use an SSH Key" checkbox and upload your private key file.
Once you have input your account and credential information, you need to validate your connection on the Tables tab. Click "Connect" to continue. Note that we **do not** change error message coming from the database.
If you can successfully connect to the database, you can now select the **tables** you want to extract data from. Alternatively, you can switch to the "query-based" tab to write one or more SQL queries to extract data from the database.
You can select either Table or Query-based. You cannot select both.
# ProjectMark
Source: https://docs.less.tech/sources/guides/projectmark
The ProjectMark source loads CRM and opportunity data from ProjectMark, including endpoints that require a company scope.
Provide your **ProjectMark API Bearer token** and **Company ID**. Contact their support for assistance.
Select the **ProjectMark tables** you want in Less.
# QuickBooks Online
Source: https://docs.less.tech/sources/guides/quickbooks
The QuickBooks Online source uses **OAuth** to access your Intuit company and extract accounting entities into Less.
Complete Intuit sign-in. Less stores a **refresh token** and usually fills in your **Company ID (Realm ID)** automatically; you can correct it manually if needed.
Choose an **update type**: **Full** replaces all data on each update; **Incremental** only pulls changed records when supported.
Select the **QuickBooks entities** (customers, invoices, accounts, and so on) to extract.
# QuickBooks TSheets (Time)
Source: https://docs.less.tech/sources/guides/quickbooks_tsheets
The QuickBooks TSheets source uses a **Bearer token** to read time and payroll-related data from TSheets within the date window you specify.
Paste your **TSheets API Bearer token**.
You can see how to create an API Bearer token on QB Time's [documentation](https://tsheetsteam.github.io/api_docs/#obtaining-an-api-access-token)
Select the **date range** for extraction. Payroll-oriented data is retrieved day by day across that range.
Choose which **TSheets tables** to load into Less.
# SharePoint
Source: https://docs.less.tech/sources/guides/sharepoint
You can use the Sharepoint source to extract CSV, Excel and Parquet files from your Sharepoint sites.
### Setup
The setup to extract data from Sharepoint is straightforward. You need to authenticate, select files and then adjust the data that we'll extract if needed.
Start by clicking the "Authenticate with Microsoft" button. This will open a new tab where you can sign in with your Microsoft account.
After signing in, you'll be redirected back to the Less page. We'll now fetch your SharePoint directories and sites. Once that's done, you can browse and select the files you want to extract.
You can always refresh the list of directories and sites by clicking the "Refresh" button. You can also always re-authenticate by clicking the "Re-authenticate with Microsoft" button again.
In the second step, you see each of your files as expandable items. It looks like this:
We scan each file to help you customize the extraction. We based this on the first 20 rows of the file.
For **CSV** files, you can select the **encoding**, **delimiter**, **skip rows** and **columns**. The columns are based on the suggested skipped rows - i.e. if we suggest to skip 3 rows, the columns will be the first row after the skipped rows.
For **Excel** files, you can select the **sheet** you want to extract. You can select more sheets if you want. For each sheet you can input the number of rows to skip and the columns to extract.
For **Parquet** files, you can select the **columns** to extract.
# Shopify
Source: https://docs.less.tech/sources/guides/shopify
This source is incremental by default. This means only new data will be extracted on each run.
The Shopify source allows you to extract Customers, Orders, Abandoned Checkouts, Collects, and Products from your Shopify store into Less.
# Snowflake
Source: https://docs.less.tech/sources/guides/snowflake
You need to make sure the Less IPs are whitelisted in your Snowflake account. You can find the IPs [here](/guides/less-ip).
You can also choose to use PAT (programmatic access tokens) instead of the password.
You can find most of the information you need from Snowflake here. You also need a compute warehouse which you can find under Compute in the left sidebar of Snowflake. Lastly, you need the name of database you want to extract data from.
### Password or Service Account Setup
There are three parts to setting up a Snowflake source.
The first step is input **account identifier**, **compute warehouse**, and the name of the **database** you want to extract data from.
Step two is to input a **role** (see the GIF above to find it in Snowflake). Secondly, you need to select your **authentication type**. By default, you can only choose "Password". You can enable OAuth 2.0 authentication as well (see below).
Input your **username** and **password** if you choose "Password" authentication. Alternatively, click "Authenticate with Snowflake" if you have enabled OAuth 2.0 authentication.
We're working on enabling Service Account authentication
Once you have input your account and credential information, you can test your connection on the Tables tab. Click "Connect" to continue. Note that we **do not** change error message coming from Snowflake.
If you can successfully connect to Snowflake, you can now select the **tables** you want to extract data from.
### OAuth 2.0 Authentication
Admins and Super Admins can enable the users in your Less workspace to connect to Snowflake with OAuth 2.0 authentication. To do so, you need to first create a custom OAuth 2.0 application in Snowflake. You can find the instructions [here](https://docs.snowflake.com/en/user-guide/oauth-custom).
This is rather complex. Reach out to us if you want our help with setting up Snowflake OAuth 2.0 authentication.
Once you've created the OAuth 2.0 application in Snowflake, navigate Settings -> Other and click "Connect" in the Snowflake OAuth settings section. There you'll need to input the following:
* **Client ID**: The Client ID of the OAuth 2.0 application you created in Snowflake.
* **Client Secret**: The Client Secret of the OAuth 2.0 application you created in Snowflake.
* **Authorization URL**: The Authorization URL of the OAuth 2.0 application you created in Snowflake.
* **Token URL**: The Token URL of the OAuth 2.0 application you created in Snowflake.
Click "Save Settings" to continue.
Once you've saved the OAuth 2.0 application, you can now connect to Snowflake with OAuth 2.0 authentication when setting up a Snowflake source.
# Toddle
Source: https://docs.less.tech/sources/guides/toddle
The Toddle source connects to the Toddle API to extract curriculum, assessment, and attendance-related data for the region and dates you configure.
Enter your **Toddle API bearer token** (from your Toddle administrator or contact Toddle Support) and the **region** for your instance (for example `me-central-1` or `us-east-1`).
Choose the **date range** used when pulling attendance (and other date-bounded) data.
Select the **Toddle tables** to extract into Less.
# Veracross
Source: https://docs.less.tech/sources/guides/veracross
The Veracross source uses **OAuth** against your school’s Veracross API to extract student, staff, class, etc.
Enter your **School route** (the subdomain from your Veracross URL), plus the API **Client ID** and **Client Secret** issued for Less or your integration user.
You can read more about OAuth on Veracross' [documentation](https://community.veracross.com/s/article/OAuth-Applications-and-Veracross-Overview).
Choose which **Veracross tables** to load into Less.
# Viewpoint Vista
Source: https://docs.less.tech/sources/guides/viewpoint
The Viewpoint Vista source uses the **Trimble XChange** API together with your subscriber details to pull construction ERP data modified within a date window.
Provide your **Trimble XChange API key** and **Subscriber code**. Obtain the API key from your TC1 sales representative if you do not already have one.
Set the **date range** of interest. Only records **modified** within that range are extracted.
Select the **Viewpoint Vista tables** to bring into Less. These spend across job costs, payroll, AR/AP, GL, equipment, headquaters and project management.
# WooCommerce
Source: https://docs.less.tech/sources/guides/woocommerce
This source is incremental by default. This means that new data will be extracted on each run.
The WooCommerce source allows you to extract Orders, Customers, Products, Product Variations and Coupons from your WooCommerce store into Less.
### Setup
There are three steps you need to configure for the WooCommerce source: Credentials, Date Interval and Tables.
In the Credentials step, you need to input your Webshop URL, Consumer Key and Consumer Secret.
To generate the Consumer Key and Consumer Secret, you need to follow these instructions:
1. Go to WooCommerce > Settings > Advanced
2. Go to the REST API tab and click Add key.
3. Give the key a description for your own reference, choose a user with access to orders etc, and give the key read/write permissions.
4. Click Generate api key.
5. Your keys will be shown - do not close this tab yet, the secret will be hidden if you try to view the key again.
In the Date Interval step, you need to input the first/start date you want to extract data from. If you want to extract data from a fixed period, you can also input an end date.
In the Tables step, simply select the tables you want to extract into Less.
# Quickstart
Source: https://docs.less.tech/sources/quickstart
Use Sources to get your data into Less
There are two parts of sources that are present across all of them: asset input and scheduling input.
### Asset input
For all sources, you need to input a **name**. This is the name of the source that will be used to identify the source in the Less platform. The **description** is optional.
You can also choose to add a table prefix to the source name. If you have for instance have multiple Shopify webshops, you should add the webshop name as a prefix to the source name. This is helpful to distinguish between the tables that the Sources creates.
If you change the prefix later on in a Source, it will create new tables.
You also need to choose an **instance size**. You can choose from a number of different instance sizes: X-Small, Small, Medium, Large, X-Large and 2X-Large. The instance size determines how much computational power is available to run your Source. The larger the instance, the more credits you consume. Read more about [credits](/essentials/credits).
This is helpful to ensure that your sources have the appropriate amount of computational power. For a minor Source (like a Google Sheet) you can use a Micro instance, but that might not be sufficient for a database Source extracting tables with millions of rows.
You can always track how much computational power is utilized by your sources by navigating to the Job overview.
From the example above, you can see that we should perhaps try to decrease the instance size as we're only utilizing ≈15% of the computational power available.
### Scheduling input
You also always need to set a **schedule**. This is the schedule that will be used to run your source. You'll see three options: 1) never to avoid scheduling, 2) basic or 3) cron.
If you choose **basic**, you can select the interval (hourly, daily or weekly), the time of day, the timezone and the day of the week (only for weekly).
If you choose **cron**, you get full control over the schedule. Cron syntax is a powerful way to schedule your model runs. It consists of five fields:
* Minute
* Hour
* Day of month
* Month
* Day of week
For example, `0 0 * * *` would run the model every day at midnight. Where 0 in minute means at the start of the hour and 0 in hour means at the start of the day (i.e. midnight). \* means every minute, every hour, every day, every month, every day of the week so in this case every day of every month at midnight.
You could also choose to input `15 8-17/4 * * 1-5` to run your model at 15 minutes past the hour, every 4 hours, between 08:00 AM and 05:59 PM, Monday through Friday. In sum, you have full control.
You can choose from one of our presets and you can also view the 10 next times the model will run given your cron expression.
# Columns
Source: https://docs.less.tech/tools/basics/columns
Select, order, rename and change format of your columns
The Columns tool is probably the most used tool in Less. It is quite a swiss army knife that can be used for a number of things: changing the order of your columns, selecting a subset of the columns you want to keep in your dataset, renaming column names and changing the data types of your columns.
### Configuration
The Columns tool consists of one required input and three optional.
It is mandatory to select minimum one column to keep in your dataset. You can use the checkboxes to the left of the column name to keep the given column.
You can select/deselect all columns with the checkbox in the header row of the configuration window
You can rename your column names in by entering a new name in the "Rename Column" tab in the configuration windows. This is optional.
You can change the order of when your column appears in your dataset. For instance, you might want your ID columns to be the first in your dataset. You can change the order by dragging the given column up or down with the drag button all the way to the left in the configuration window.
You can change the column data type in the dropdown to the right in the configuration windows. For instance, changing a text/string column to a decimal/float data type.
### Configuration overview
Here you can view each of the options in the configuration window.
1. Select all columns
2. Deselect all columns
3. Show selected columns
4. Search for a column
5. Drag this to reorder the columns
6. Move a column to the top
7. Check this to select the column
8. Rename the column
9. Change the data type of the column
# Create Rows
Source: https://docs.less.tech/tools/basics/create-rows
Create new rows in your dataset
The Create Rows tool is helpful for generating news rows in your dataset. For instance, generating all the dates between a start and an end date.
To exemplify, you dataset could contain three rows with a newRows column that contains 1, 2 and 3 respectively as well as an amount column that contains 300.
With the Create Rows tool, you can create 0, 1 and 2 new rows respectively for rows shown in the dataset above. That would lead to the following dataset:
Note that Less automatically generates the *row\_number* column in your dataset when you use the Create Rows tool. You can use the second input (see configuration below) to automatically disaggregate columns based on how many news rows that are being created in the dataset.
By selecting to disaggregate the *amount* column in the dataset above, you'd get the column shown in the screenshot above - it essentially divides 300 by the number of new rows to create (i.e. 300 / 1 = 300, 300 / 2 = 150, 300 / 3 = 100).
### Configuration
The Create Rows tool has one required input and an optional input.
Select the column that contains an integer/whole number which represents the number of new rows you would like to create for the particular row in your dataset.
The values of the column doesn't have to be different; you can use a [New Column](/tools/new-columns/new-columns) tool to create a static number representing the number of rows you would like to create in your dataset.
This is an optional step. Select the column(s) that you want to disaggregate based on the number of rows that are being created. Behind the scenes this columnn is divided by the number of rows being created.
### Example
Imagine we have a dataset that looks like this:
We have calculated the difference in days between a start and an end date. We want to create a new row for each day between the start and end date. We also want to disaggregate the *amount* column by the number of days between the start and end date.
We use the dateDiff column to generate the number of new rows to create. We then use the amount column to disaggregate the amount by the number of days between the start and end date. We end up with 15 rows - 10 for the first original row and 5 for the second original row. The amount column has been divided by 10 in the first case and by 5 in the second case.
# Destination
Source: https://docs.less.tech/tools/basics/destination
Store tables
The Destination tool is used to send data outside of Less. That could be to databases like Snowflake, send emails with Gmail, or to a Microsoft Sharepoint.
When using the Destination tool, your table is **not** stored in Less. It is sent to the destination you have selected.
Before using the Destination tool, you need to create a destination. You can learn more about that here [Destinations](/destinations/quickstart).
The Destination tool works by referencing the destination that you already created. That means you don't have to log in or authenticate, but simply select the destination you want to use and fill in a couple of fields (such as a table name for databases).
As a result, each Destination tool differs by the type of destination you want to use (e.g. Snowflak, Gmail, Microsoft Sharepoint). We'll add documentation as we add new destinations types below.
This input supports parameter syntax
Select the table name that you want to create in Snowflake. If you are appending or upserting, you need to specify a table name that already exists in Snowflake.
1. Overwrite. This will overwrite the existing table with the new data every time the Destination tool runs.
2. Append. This will add all the new rows to the existing table. Over time there's a risk that you will create very large tables - use this option with caution.
3. Upsert. This requires selecting a column to use as a unique identifier. The upsert operation will then look for that ID in the table and update the existing rows with the new data (when it finds a row with that ID). If the row does not exist, it will insert a new row.
Select the column that you want to use to upsert the data. You need to ensure that this column exists in the table you are upserting to.
# Directory
Source: https://docs.less.tech/tools/basics/directory
Load multiple tables
The Directory tool can we used to load and stack (union) multiple tables with one tool. You can also control which tables you want to load with your Canvas parameters.
### Configuration
This input supports parameter syntax
Input a pattern that correspondxs to the tables names you want to import. This
uses wildcards to match table names. You could - for instance - write *testDataset*\*
to get all the tables whose name begins with *testDataset*.
You can use the following to get started with pattern matching:
* \* matches any number of characters (including none). Example: *dataset\** matches dataset\_1, dataset\_abc but not hello\_dataset\_1
* ? matches any single character. Example: *data\*?.csv* matches data\_a.csv, data\_1.csv but not data\_123.csv
* \[seq] matches any character in seq. Example: *file\[12].csv* matches file1.csv and file2.csv but not file55.csv
If selected, you can restrict the tables being matched to only come from a
certain folder. This requires you to input the revelant folder ID (which you
can find from the URL when navigating to a folder). This might be helpful if
you want to ensure you don't match any undesired tables.
This input supports parameter syntax
This input is only shown if *Folder matching* above is enabled.
You should input the ID of the folder you want to restrict tables coming from here.
You can choose to limit the number of files being loaded. If you're working with less restrictive patterns such as \*.csv, it could be quite helpful to restrict the number of files as you might otherwise end up with very large combined tables.
You can choose to limit the number of rows being loaded from each file. If you're working with large datasets, it could be helpful to begin by restricting the number of rows while you validate what's being loaded.
By enabling this option you place a restriction that all tables that are loaded must have exactly the same columns. If one of the tables doesn't, then the Directory tool will fail. This is helpful if you know that all tables should match 1:1 in their structure and if they don't then it must be because of a wrong table being loaded.
### Example
In this example, we want to use a Parameter to match all tables beginning with *testDataset*. We only want to import 2 tables and each you be limited to 10 rows. We don't need tables to match each others structure (no column matching) and we don't care if tables come from different folders (no folder matching).
You'll notice a couple of things here.
1. We only have 20 rows. That seems correct. Maximum 2 tables each limited to 10 rows = a total of 20 rows
2. We're using our *fetch* parameter to get the \*testDataset\*\* pattern into our Directory tool. We use this to match two tables: *testDataset* and *testDataset123*
3. We have an origin column showing the original table name of each row - we can use this to track where our data originates from
4. We have a column called *from* in our *testDataset123* that is not present in *testDataset*. That's fine because we disabled column matching
# Dynamic Rename
Source: https://docs.less.tech/tools/basics/dynamic-rename
Dynamically change your column names
The Dynamic Rename tool can be used to dynamically change the name of your columns in three different ways.
The *H* input anchor in the Dynamic Rename tool is optional. You only need to use this if you want to map column names in the first anchor with new names (D) from the second anchor (H).
The first way is to add a prefix to your column names.
The second way to dynamically rename is to fetch a column name from one of your rows in your dataset.
The third way to use the Dynamic Rename tool is to dynamically map your column names to another dataset - like a find and replace for column names. If you want to use the Dynamic Rename tool in this way, you need to connect a dataset to the *H* anchor.
The third option can be very powerful if you work with changing datasets. You can use it to map your columns to a predefined schema and then use a [Columns](/tools/basics/columns) tool to only select the columns that match the schema.
### Configuration
Select how you want to use the Dynamic Rename tool.
Simply input the prefix that you want to add to your column names.
Simply input the row number that contains your new column names.
**To activate this version of the Dynamic Rename tool, connect a dataset to the *H* anchor. See the exampels below**
Select the column containing the column names from your *H* anchor dataset to look up in your D anchor.
Select the column from your D dataset that should replace the existing column names.
### Example: Excel File with Column Headers in a Specific Row
I have imported an Excel file with my column header in the the second row. I want to make them my column headers.
### Example: Map Column Names to Another Dataset
We have a dataset with column names with the following names: text\_col, float\_col, int\_col. We want to change them to Text Column, Decimal Column, Integer Column.
# Fill
Source: https://docs.less.tech/tools/basics/fill
Populate NULLs
The Fill tool can be used to get rid of null values in your dataset. You can use a variety of filling options to either populate nulls with a fixed value or to dynamically fill your null values with the other values of your dataset.
### Configuration
Select the column(s) you want to fill. You can choose multiple columns at the same time.
Select how you want to fill the column(s) selected in Step 1. You can choose from five different methods:
* **Number**: use this option to hardcode a static value. Note that this transforms the column to a text/string column.
* **Text**: use this option to input zero in your null columns. This option only works with whole number/integer and decimal/float columns.
* **Zero**: use this option to input zero in your null columns. This option only works with whole number/integer and decimal/float columns.
* **Down**: use this option to fillcell values forward/down in your dataset. See the Examples below for context.
* **Up**: use this option to fill cell values backward/up in your dataset. See the Examples below for context.
Number and Zero only work with Interger and Decimal columns, Text only works with Text columns while Up and Down woks with all columns types.
# Filter
Source: https://docs.less.tech/tools/basics/filter
Remove rows with conditions
The Filter tool is one of the most used tool in any data analytics process. The Filter tool is designed to selectively pass through data that meets one or more conditions. In other words, you make a rule that each row has to fulfill and in doing so the output of your Filter tool will typically be a smaller dataset measured by the number of rows. You can use it to remove or keep null values, keep rows where an amount column is larger than a value or remove rows where a text column does not equal a certain requirement.
The Filter tool outputs two anchors. That means you can easily access the rows that pass through the filter and the rows that don't.
### Configuration
You can use the Filter tool for simple operation but it can also be set up to handle more complex conditions. For each condtion you'll add, you need to configure the following:
Select the column you want to filter by. This column will be used as the foundation for your condition.
Select the operation that you want to filter your column by. Selecting the column determines which operations are available.
This input support syntax, column references and parameters.
Enter the syntax that you want to filter with. See our [Syntax](/canvas/syntax) page for more information. If you input raw text (like "Hello World") you need to wrap it in double-quotes. To get the TRUE value of a boolean use 1 - and 0 for FALSE.
In addition to the above, there are a number of other options that you can configure:
1. Convert an outer condition to a group condition. This is useful if you want to group multiple conditions together.
2. Switch between AND and OR clauses for the outer conditions.
3. Inside a group condition, you can also switch between AND and OR clauses for the group conditions.
4. Add a group condition. This is useful if you want to group multiple conditions together.
5. Remove a group condition. This is useful if you want to remove a group condition.
6. Add an outer condtion. This is useful if you want to add a condition to the outer conditions.
### Example: Keeping null values
In this example, we want to keep the rows where the column is null. We simply select the "is null" operation and leave the syntax empty.
### Example: Filtering with contains in a Text column
In this example, we want to keep the rows where the *text\_col* column contains the text "1". Notice the double quotes around the text "1".
### Example: Creating a date range using a dynamic date
In this example, we only want to keep transactions that occur after a fixed date but before the current date. We use the Today constants in the syntax input and use two outer conditions to create a date range.
### Example: Filtering Boolean columns
In this example, we want to keep the rows where the *boolean\_col* column is true. Notice how select the "is true" operation and leave the syntax empty.
### Example: Creating nested conditions
In this example, we want to keep the rows *nulls\_col* is null **or** where *int\_col* is larger than 500 **and** where *float\_col* is less than 0.3. Note that the nested group condition must both be true (because of the AND clause) **OR** the first condition must be true (because of the OR clause).
### Example: Advanced syntax
In this example, we want to keep all rows where *datetime\_col* is equal to today's date minus 2 years truncated to the first day of the year.
# Input
Source: https://docs.less.tech/tools/basics/input
Load a single table
The Input tool is where most models begin (unless you're using a [Manual Input](/tools/utilities/manual-input.mdx) tool). You can use it to load data to the Canvas.
You can search by table name at the top of the configuration window. Whenever you hover a table, you'll see more information about the number of rows, columns, the tables status, what it's generated by and when it was last updated.
You can use the Row limit at the end of the configuration window to limit the number of rows that you import. This is useful when building models with large datasets that you want to reduce the size of while building. Typically users remove this when productionizing models.
# Limit
Source: https://docs.less.tech/tools/basics/limit
Reduce the number of rows in your data set
The Limit tool can be used to reduce the size of your dataset. It can be useful if you're working with large datasets and want to increase the performance while you're building your model. Once you're model is ready for production, you can always remove the Limit tool again to ensure that your model is using the full dataset.
### Configuration
All you have to do is input the number of rows you would like to reduce you
dataset to.
If you want to limit the dataset within a group, you can select the group by column(s) here.
### Example: Limiting within a group
Imagine we have a dataset that looks like this:
We want to limit the dataset to 1 row per group (true and false in the *bool\_col* column). We can do this by selecting the group by column and then selecting the limit tool.
# Replace
Source: https://docs.less.tech/tools/basics/replace
Replace text values in one or multiple columns
The Replace tool is used to replace text values in columns with a new value. It is typically used when either preparing the input data for analysis or before outputting to a table to ensure that the data is in the right format for your reporting/activation layer.
The Replace tool can only be used with text/string columns
### Configuration
Select the column(s) in which you want to replace a value. You can choose multiple columns.
Input the value or pattern you want to replace. If you're using a literal value, you can simple input your text (no need to wrap it in double-quotes). The replace tool will then look for this value in the column(s) you selected. Alternatively, you can input a RegEx pattern if the literal is switched off in Step 5.
This input supports syntax - column references, syntax and parameters
Input the value you want to replace the pattern with. You can reference existing columns in your dataset to dynamically replace values.
If you want to replace with a raw text value, you need to wrap it in double-quotes.
Choose whether to replace all occurrences of the value or pattern or only the first occurrence.
Choose whether we should intepret your pattern as a literal value or a RegEx pattern.
### Example: Replacing spaces with underscores
In this example, we want to replace all spaces with underscores in the *column\_1* column. We can do this with a RegEx patterns, disable the literal option and select the replace all option.
### Example: Replacing simple text values
In this example, we want to replace "text" with "TEST" in the *text\_col* column. We can do this with a literal value and by enabling the literal option.
### Example: Replace all special characters with a parameter values
In this example, we want to replace all special characters in the *date\_string2* column with a parameter value. We can do this by referencing our *replacement* parameter in the value input, using the a RegEx input in the pattner syntax and disabling the literal option.
# Save Table
Source: https://docs.less.tech/tools/basics/save-table
Store tables in Less
You can use the Save Table tool to store tables inside Less. You need to input a table name and choose whether to overwrite or append the potentially existing table.
If you want to send data outside of Less, you can use the [Destination](/tools/basics/destination) tool.
It is most common to **overwrite** tables. This will overwrite the existing table with the new table data every time the Save Table tool runs.
If you choose to **append** the table, you will add all the new rows to the existing table. Over time there's a risk that you will create very large tables - use this option with caution.
### Where does the table get stored?
You table is stored in file-storage hosted by Less. This is a fast and efficient way to store tables inside Less that we opt for because its optimized for data analytics.
If you're an Enterprise customer, you can choose to self-host the file-storage. Reach out to us if you want to learn more about this.
### Advanced options
Tables names are not unique in Less. Each tables has a unique identifier. That means that if you want to append to a table, that is generated by another model, then you need to specify the exact table you want to overwrite or append to.
You can do that with the advanced options. You can select the exact table you want to overwrite or append to which will disable the table name input field.
In the screenshot above, you can see that we're in a model called "New Model". We want to overwrite a specific table called "testDataset" which is originally generated by a model called "Demo Model". You do not need to make any changes to the "Demo Model". This will ensure that "New Model" will always overwrite the same table - "testDataset" generated by "Demo Model".
# Sort
Source: https://docs.less.tech/tools/basics/sort
Sort the rows in your dataset
The Sort tool is simple but one of the most used tools. It can be used for a steps in an analytics workflow, but is also often used for exploratory data analysis. It changes the order in which your rows are shown in the dataset by sorting one or many columns either ascending or descending.
The order in which you sort matters! The first pair of columns and sorting direction will be applied first, followed by the second pair, etc.
### Configuration
The Sort tool only has one required multi-select input.
Select the column you want to sort by in the tool configuration.
Choose whether to sort the column ascending (small values at the top) or descending (large values at the top).
You can add as many pairs of columns and sorting directions as you want. You can use the up and down arrows to the left to change the order of the columns and build your own sorting hierarchy.
### Example: Why the order matters
First let's look at the dataset before we sort it.
Now let's sort the dataset by the *value* column ascending and then by the *date* column ascending.
We can see the it has started by sorting the dataset by the *value* column ascending: 1, 2, 2, 2, 3. For the order of the rows with the value 2, it has sorted by the *date* column ascending: 2025-01-13, 2025-03-08, 2025-09-27.
Now let's sort the dataset by the *date* column ascending and then by the *value* column ascending.
Now we can see the first we sort by the date and when we hit two similar dates (2025-03-08), it has sorted by the *value* column ascending: 2 first and then 3.
# Transform
Source: https://docs.less.tech/tools/basics/transform
Change column apparance
The Transform tool is a multi-purpose tool that can be used to change both text and numeric columns. Its purpose is to format the given column into a certain shape, such as making a text column UPPERCASE or rounding a decimal columns to 2 decimals.
### Configuration
Select the column(s) you want to transform. You can choose multiple columns at the same time.
Choose how you would like to change your column(s) from the options below:
| Option | Description | Column format requirement |
| ------------------------- | ---------------------------------------------------- | ------------------------- |
| Upper Case | CHANGES COLUMN CONTENT TO UPPERCASE | Text |
| Lower Case | changes column content to lowercase | Text |
| Title Case | Changes Column Content To Titlecase | Text |
| Left | Get the first *x* number of characters of a column | Text |
| Right | Get the last *x* number of characters of a column | Text |
| Length | Set the maximum *x* number of characters of a column | Text |
| Round | Round a numeric column to *x* number of decimals | Numeric |
| Ceil | Round up to nearest integer/whole number | Numeric |
| Floor | Round down to nearest integer/whole number | Numeric |
| Trim | Remove trailing/leading whitespace and tabs | Text |
| Escape Special Characters | \n show tabs as \n | Text |
| Remove special characters | removeunderscoresthatusedtobebetweenwords | Text |
| Encode | Encode as either HEX or Base64 | Text |
| Decode | Decode as either HEX or Base64 | Text |
# Unique
Source: https://docs.less.tech/tools/basics/unique
Remove duplicate rows
The Unique tool enables you select one or several columns that should be unique whereby all the duplicate rows are removed.
The Unique tool keeps the first rows that is unique and discards all the
following duplicates
The Filter tool outputs two anchors. That means you can easily access the rows that pass through the filter and the rows that don't.
Note that when you select multiple columns, you create column pairs behind the scenes - almost like combining the two (or more) columns into a new column. If you dataset looks like this:
| amount | text |
| ------ | ----------- |
| 100 | Hello |
| 200 | World |
| 300 | World |
| 200 | Hello World |
| 100 | hello world |
There are then three possible options and output:
1. **amount** should be unique which outputs the first three rows
2. **text** should be unique which outputs the first two rows and last two rows
3. **amount** and **text** should be unique which outputs all five rows
### Configuration
Select the column(s) you would like to be unique. You can select one or
many.
The order in which you select multiple columns does not matter for the
Unique tool
The Unique tool is case sensitive meaning *This* and *this* are two
different and unique values
# Append
Source: https://docs.less.tech/tools/merge/append
Attach a column(s) to another dataset
The Append tools combines each row of your first dataset with each row of your second dataset. It is typically used when you want to "attach" a couple of columns of static data to a larger dataset.
Be careful with the Append tool. The Append tool works by combining every row from each of the two input datasets. So if you have 10 rows in dataset one and 100 rows in dataset two, you will create an output of 1.000 (10 \* 100) rows by appending them. This is also known as a cross join or a cartesian product and will slow down performance. If you have 10.000 rows and 10.000 rows, you will create an output of 100.000.000 - i.e. it quickly produces **significant** datasets.
## Configuration
The Append tool doesn't require any configuration. But you can add a custom suffix to any potential duplicate columns to avoid conflicts.
# Close Combine
Source: https://docs.less.tech/tools/merge/close-combine
Merge datasets where IDs almost match
The Close Combine tool is used to merge datasets where the IDs almost match. It is typically used with datetime columns. It can be quite complex to get used to but once you get the hang of it, it is a powerful tool.
We'll start of with an example. We have two datasets - each with a datetime column. We know the two dates doesn't match. However, we want to look up the nearest date looking forward in the other dataset. We have a maximum tolerance of the two dates being 90 days apart.
As you can see, we're able to match two of our dates from the left dataset with the right dataset. 2023-02-28 is matched with 2023-03-20 because its within the tolerance of 90 days. Same logic applies to 2025-08-03 and 2025-08-10. However, no date in our right dataset is within 90 days of 2024-11-02 whereby the row from the left dataset is not matched.
Notice how 2025-08-01 is technically closer to 2025-08-03 than 2025-08-10 in the right dataset. However, because we're looking for the nearest date looking **forward**, we're not able to matching it with 2025-08-01. We could change that by looking backward or nearest. The very important thing to notice is how it matters which of our datasets is the left (L anchor) and which is the right (R anchor).
If we changed our strategy to backward, we would get the following results.
### Configuration
Choose the column from the left dataset that you want to use to combine with the right dataset.
Choose the column from the right dataset that you want to use to combine with the left dataset.
Choose the strategy you want to use to combine the datasets. You can choose between forward, backward or nearest:
* Forward: Look for the nearest similar value looking forward/down in the right (R) dataset. If two values are the same, the first one (from the top going downwards) is chosen.
* Backward: Look for the nearest similar value looking backward/up in the right (R) dataset. If two values are the same, the first one (from the bottom going upwards) is chosen.
* Nearest: Look for the nearest similar value in the right (R) dataset. If two values are the same, the first one (from the top going downwards) is chosen.
When you're combining datetime columns, you can add a tolerance to the comparison. This is the maximum duration that the two dates can be apart. You can choose between:
* None: all values are matched regardless of the duration between them.
* 1 second
* 1 minute
* 1 hour
* 1 day
* 1 week
* 30 days
* 90 days
* 365 days
You can choose to combine **first** by some other columns from each dataset. This is like a built-in [Combine tool](../tools/merge/combine) where you choose the columns you want to combine by before doing the close combine.
You can choose to add a suffix to potential duplicate columns. Otherwise, we add a default suffix to duplicate column names in the right dataset.
### Example: The illustration example 👆
Here we're showing exactly how to configure the tool to get the same results as the first illustration example above.
### Example: Using the 'by columns' feature
In this example, we want to **first** combine on the *text\_col* from the left dataset to the *joinBefore* from the right dataset. This will act as a filter to only combine the rows where the *text\_col* is the same as the *joinBefore* column.
We also use the nearest strategy with a tolerance of 90 days.
As we can see only the first row from the left dataset is combined with the right dataset. That's because this is the only row where the *text\_col* is the same as the *joinBefore* column.
# Combine
Source: https://docs.less.tech/tools/merge/combine
Merge datasets horizontally
The Combine tool is probably the most important and used tool in Less. It is used to merge datasets horisontally via one of more IDs.
The Combine is called a Join in SQL, Merge in Pandas and XLOOKUP in Excel.
Imagine you have two lists of friends - one list has their names and favorite colors, and another list has their names and favorite foods. A Combine is like putting these lists together by matching the names! You get three results: friends who appear in both lists (with all their info), friends who only appear in the first list, and friends who only appear in the second list. It's like making a super list that has everything from both your original lists!
In technical terms, the Combine tool outputs three anchors - just like how we got three different friend lists in our example above. That means you can easily access the rows that combine, the ones that don't combine from the **left** dataset and the ones that don't combine from the **right** dataset.
## Configuration
Note that the *L* and *R* of the Combine anchors refers to *left table* and *right table* respectively.
Choose which columns to use as ID columns. The right column refers to the R anchor and the left column refers to the L anchor.
The ID columns must be the same data type.
You can add as many ID columnn pars as you need with the "+ Add pair"-button. Check out the examples below.
You can choose to add a suffix to the output columns. This is useful if you potentially have duplicate columns in your datasets.
You can choose to select the output columns in dataset. This is like a built-in [Columns](../basics/columns) tool (though slightlty less sophiscated).
### Example: Single ID column
Here we have a simple example where we want to combine on *text\_col* (L) and *combineCol1* (R).
We deselect a lot of columns from the left dataset while we're at it.
### Example: Multiple ID columns
Here we combine with two column pairs. Notice how - as opposed to the example above - we only match a single row because this row matches both of our column pairs.
# Stack
Source: https://docs.less.tech/tools/merge/stack
Merge datasets vertically
The Stack tool takes two datasets and stacks them on top of each other vertically. It stacks columns with the same name on top of each other. If some columns (e.g. *revenue* and *amount* below) are only present in one of the datasets, the columns will still be stacked but the row values will be *NULL* in the rows from the other dataset where the column is not present.
Columns with the same name that should be stacked must have the same data type
You can add as many incoming datasets as you want.
### Configuration
You have two optional configuration steps:
By enabling this option you place a restriction that all tables that are stacked must have exactly the same columns. If one of the tables doesn't, then the Stack tool will fail. This is helpful if you know that all tables should match 1:1 in their structure.
You can choose to customize the order in which the datasets are stacked.
# Add Business Days
Source: https://docs.less.tech/tools/new-columns/add-business-days
Add business days while accounting for holidays
The Add Business Days tool is used to add a number of business days while accounting for holidays. You can use the [Date Math](/tools/new-columns/date-math) tool if you're just looking to add days.
The Add Business Days tool outputs two anchors. The "Holidays" anchor contains the holidays that were used to calculate the new date - use this to validate the holidays that were used. The "Data" anchor contains the primary data with the new date column.
### Configuration
If you want to bring your own holidays data, you need to connect your primary data to the *D* anchor and the dataset containing your holidays to the *H* anchor. Check out the examples to see how.
The Add Business Days tool will create a new column. Use this input to name it.
Select the column in your primary data containing the date to which you want to add a number of days.
Select the column in your primary data that contains the number of business days that you would like to add to your date column from Step #2.
Select whether you 1) don't want to account for holidays, 2) want to account for holidays and want to use our built-in holidays, or 3) want to account for holidays and have your own holiday data.
If you choose to use our built-in holidays, you can specify the country that you want to use for the holidays.
For some countries there are optional holidays that can be included. For instance, in Denmark, December 24th is technically not a public holiday, but it is a closing day under the Danish Closing Act. Such examples exist and can be included with the holday categories input.
If you choose to use your own holiday data, you need to specify the column in your holiday data (dataset connected to the *H* anchor) that contains the holiday dates.
### Example: Accounting for holidays
In this example, we want to add the integer value of business days in our *simple\_int* column to our *datetime\_col* column. We want to account for holidays in Spain and use our built-in holidays.
Notice that the *H* anchor is empty. This means that we want to use our built-in holidays. Secondly, look at row 5. The start date is Jan 5th 2023 (a Thursday) and we want to add 5 business days (the value in the *simple\_int* column). The output date is Jan 13th 2023. Here's why.
Jan 6th is skipped because it Epiphany in Spain. The weekend is also skipped whereby our 5-day count begins on Monday, Jan 9th and ends on Friday, Jan 13th which becomes our output date.
### Example: Accounting for holidays and using your own holiday data
You can also bring your own custom holiday data. That might be relevant if your company has its own holiday calendar. In the example below, we have connected the *H* anchor to a custom holiday dataset.
Our custom holidays for the above example is Jan 9th, 10th and 11th whereby row 5's output date is Jan 17th.
# Compare
Source: https://docs.less.tech/tools/new-columns/compare
Move values vertically
The Compare tool can be used to move cell values up or down in your dataset. It helps you look at the previous or subsequent rows relative to your current row. You can think of it as looking back (up in the dataset) or forward (down in the dataset) to see what happened before or later in your dataset. It is typically used after sorting by a column (oftentimes a date column).
The Compare tool is similar to a LAG function in SQL. If you're looking for more advanced ways to do row-wise calculations check out the [Cumulative](/tools/new-columns/cumulative), [Running Interval](/tools/new-columns/running-interval) or [Loop](/tools/utilities/loop) tool
### Configuration
The Compare tool has of two required input and one optional input.
Add a prefix to your output columns.
Select the column(s) that contains the values you would like to move vertically in your dataset
Input the number of rows backward/up or forward/down that you want to fetch data from relative to your current row. Note that to look forward/down you need to input a negative value.
This is an optional input. You can use it to segregate what you are comparing with into groups. It means you're moving rows within a group defined by the values of the column(s) you select here.
This configuration is similar to a PARTITION in SQL
### Example: Getting the previous row inside a group
In this example, we want to get the previous row (lookback = 1) inside a group - our *bool\_col* column.
Notice that the 1st and 4th row are null. The is because there is no previous row for the 1st row and the 4th row. The 4th row is null because there is no previous row inside the *bool\_col* which on the 4th row is FALSE - as opposed to TRUE for the other rows.
The value of the *gorupDemo\_simple\_int* for row 2 is then 1 because 1 is the value of the *simple\_int* column on row 1 and because both are within the same group (TRUE in *bool\_col*).
# Correlation
Source: https://docs.less.tech/tools/new-columns/correlation
Calculate Person and Spearman correlations between two columns
The usage of the Correlation tool is quite narrow. It takes two columns and generates a correlation coefficient between the two columns.
## Configuration
The Correlation tool has of three required input.
Select the first column
Select the second column
Choose whether you want to perform a Person or Spearman correlation.
# Count Business Days
Source: https://docs.less.tech/tools/new-columns/count-business-days
Add the number of days to two dates while accounting for holidays
The Count Business Days tool can help you count the number of business days between two dates while accounting for holidays.
The Count Business Days tool outputs two anchors. The "Holidays" anchor contains the holidays that were used to calculate the new date - use this to validate the holidays that were used. The "Data" anchor contains the primary data with the new date column.
### Configuration
If you want to bring your own holidays data, you need to connect your primary data to the *D* anchor and the dataset containing your holidays to the *H* anchor. Check out the example to see how.
The Count Business Days tool will create a new column. Use this input to name it.
Select the column in your primary data containing the start date from which to begin counting.
Select the column in your primary data containing the end date at which to end counting.
Select whether you 1) don't want to account for holidays, 2) want to account for holidays and want to use our built-in holidays, or 3) want to account for holidays and have your own holiday data.
If you choose to use our built-in holidays, you can specify the country that you want to use for the holidays.
For some countries there are optional holidays that can be included. For instance, in Denmark, December 24th is technically not a public holiday, but it is a closing day under the Danish Closing Act. Such examples exist and can be included with the holday categories input.
If you choose to use your own holiday data, you need to specify the column in your holiday data (dataset connected to the *H* anchor) that contains the holiday dates.
### Example: Counting business days using own, custom holidays
In this example, we're using our own custom holidays dataset which contains Mon Jan 9th, Tue Jan 10th, Wed Jan 11th and Thu Jan 12th as holidays .
We connect the *H* anchor to our custom holidays and the primary data to the *D* anchor. If we look at row 1, we'll see that we're counting business days between Jan 1 and Jan 31 2023. There are 21 business days in this period (check [here](https://www.timeanddate.com/date/workdays.html?d1=1\&m1=1\&y1=2023\&d2=31\&m2=1\&y2=2023) if you're curious). We have 4 holidays in our custom holidays dataset within this period, so the output is 17 business days between Jan 1 and Jan 31 2023.
# Cumulative
Source: https://docs.less.tech/tools/new-columns/cumulative
Create cumulative columns
Use the Cumulative tool to create new columns with a cumulative sum, cumulative average, cumulative minimum, cumulative maximum cumulative product and cumulative count. It can be helpful to analyse revenue growth over time, customer retention, cumulative ROI, etc.
Typically users add a [Sort](/tools/basics/sort) tool before using the Cumulative tool to make sure their data is in the right order.
If you're looking for more advanced ways to do row-wise calculations check out the [Cumulative](/tools/new-columns/cumulative), [Running Interval](/tools/new-columns/running-interval) or [Loop](/tools/utilities/loop) tool
### Configuration
Select column you want to calculate cumulative for.
Select the operation you want to perform. You can choose between the following operations:
* Cumulative Sum (running sum of the values of the column)
* Cumulative Average (running average of the values of the column)
* Cumulative Minimum (lowest running minimum value of the column)
* Cumulative Maximum (highest running maximum value of the column)
* Cumulative Product (running multiplication of the values of the column)
* Cumulative Count (running count of the values of the column)
You can choose to reverse the cumulative calculation whereby you start from the bottom of the dataset and work your way up (instead of default - from the top).
This is an optional input. You can choose to group the cumulative calculation by a column. For instance, if you want to calculate the cumulative sum of the values of the column by a month column.
You can add any many cumulative calculations as you want by clicking the "+ Add column" button.
### Example: Cumulative sum within a group
In this example we want to sum our *simple\_int* column within each group of the *bool\_col* column.
Notice how the *cumulative\_sum\_simple\_int* column resets when the *bool\_col* column changes and starts from 1 (the value of the *simple\_int* column) again on row 5. That's because the *bool\_col* column is true from row 5 onwards and because we grouped by the that column.
# Date Difference
Source: https://docs.less.tech/tools/new-columns/date-difference
Calculate the difference between date columns in seconds, days, months, etc.
The Date Difference tool is relatively simple in its use but can fuel a lot of use cases. It's used to find the difference in number of seconds, minutes, hours, days, months or years between two dates.
Note that our Syntax also supports date difference calculations. See more in the [Syntax](/canvas/syntax) section.
## Configuration
The Date Difference tool has three required input.
Select the column containing the latest/most recent date
You can use our Current Datetime (UTC) helper if you want the latest date to be dynamic to the current date.
Select the column with the date you want to compare with. Typically this is an earlier date.
You can use our Current Datetime (UTC) helper if you want this date to be dynamic to the current date.
Select the unit you want to measure the difference in. You can select one of the following:
* Seconds
* Minutes
* Hours
* Days
* Weekdays
* Weeks
* Months
* Years
# Date Math
Source: https://docs.less.tech/tools/new-columns/date-math
Add or subtract days, seconds, hours and more from date columns
You can use the Date Math tool to extract parts of date columns - such as a weekday or year. It is particularly helpful in combinations with others tools.
Note that our Syntax also supports date math calculations. See more in the [Syntax](/canvas/syntax) section.
### Configuration
The Date Math tool will create a new column. Use this input to name it.
Select the Datetime column that you want to add/subtract a duration to/from
Select the unit you want to add/subtract to/from your date column. You can select one of the following:
* Seconds
* Minutes
* Hours
* Days
* Months
* Years
This input supports syntax, column references and parameters.
Input the number of units that you want to add/subtract from your date column. Simply put a **-** (minus) in front of the number of units to subtract instead of add.
### Example: Using syntax to add Days
In this example we want to add whatever is in the *simple\_int* column + 10 as days to the *datetime\_column* column. We simply select the *Days* unit and reference the *simple\_int* column + 10 to get the result we want.
This result is by each row. So for row 1, we add 11 days to the *datetime\_column* column. For row 2, we add 12 days to the *datetime\_column* column. And so on.
# Date Transform
Source: https://docs.less.tech/tools/new-columns/date-transform
Extract part of date columns to new formats
You can use the Date Transform tool to extract parts of date columns - such as a weekday or year. It is particularly helpful in combinations with others tools. Such as a [Filter](/tools/basics/filter) to keep transactions from the current year or a [Group By](/tools/reshape/group-by) + [Combine](/tools/merge/combine) to merge datasets by Year/Month.
Note that our Syntax also supports date trunc calculations (same as Date Transform). See more in the [Syntax](/canvas/syntax) section.
### Configuration
Select the Datetime column(s) from which you want to extract part of the date
Select the parts of the you want to extract. You can choose from the
following:
* *Date*: helpful if you just want to the date from a column that
has timestamps
* *Hour*: extract the hour from the timestamp
* *Minute*: extract the minute from the timestamp
* *Second*: extract the second from the timestamp
* *Week*: extract the ISO week from a date
* *Weekday*: extract the weekday from a date (1 = Monday)
* *Day of year*: extract the day of the year from a date (1 = January 1st)
* *Month*: extract the month from a date (1 = January)
* *Month Name*: extract the month name from a date (e.g. January)
* *First Day of Month*: get the first day of a given month from a date (e.g. 2024-10-10 → 2024-10-01)
* *Last Day of Month*: get the last day of a given month from a date (e.g. 2024-10-10 → 2024-10-31)
* *Quarter*: extract the quarter that a date is in
* *Year*: extract the year of a date (e.g. 2024-10-10 → 2024)
* *Is Leap Year*: extract whether a date is in a leap year (e.g. 2024-10-10 → TRUE)
* *Epoch*: extract the epoch from a date (e.g. 2024-10-10 → 1728518400)
# Explode List
Source: https://docs.less.tech/tools/new-columns/explode-list
Extract part of date columns to new formats
The functionality of the Explode List tool is quite narrow. It is only used with List columns to parse them into multiple rows.
Generally, as List columns are not supported in the majority of the tools, you will most likely use this tool in combination first before applying other tools.
### Configuration
Select the List column you want to parse (explode)
Select the column(s) you want to keep after exploding the List column. If you don't select any columns, the tool will remove all columns.
### Example: Exploding a List column while keeping the original
In this example, we have a simple List column that we'd like to explode and parse to manipulate it further.
We can see that the List column has been exploded into the *exploded\_list\_col* while the original is still in the dataset - *list\_col*. For each value in each row, the tool creates a new row.
# IF Column
Source: https://docs.less.tech/tools/new-columns/if-column
Create new columns with conditions
The IF Column tool is a very powerful way to create new custom columns. The best way to explain how it works is with an example. Think of it like choosing what to wear based on the weather. If it's raining, you wear a raincoat. If it's sunny, you wear a t-shirt. If it's cold, you wear a sweater.
With the IF Column tool you tell Less to make similar choices based on your data: "*If this is true, do this thing. If that's true, do that thing instead.*" Just like you check the weather before deciding what to wear, Less checks certain conditions before deciding what to do next.
The IF Column tool is also known as conditional statements, and is similar to a CASE statement in SQL and an =IF() function in Excel
Note that our Syntax also supports date math calculations. See more in the [Syntax](/canvas/syntax) section.
### Configuration
Your conditions are evaluated in the order you create them. In other words, if a cell value is equal to `Hello World` and your first condition is `IF [column].LEFT(5)="Hello" THEN "Something"` and your second condition is `IF [column].RIGHT(5)="World" THEN "SomethingElse"` then your output will rely on the **first true condition** which will lead to an output of `Something`
The IF Column tool will create a new column. Use this input to name it.
This input supports column references to overwrite a specific column as well as parameters.
Add your conditions and then clauses. The first condition and clause is required but additional ELSEIF pairs are optional. You can add them with the "+ Add condition (elseif)" button.
It is **very important** that your 'When' condition always defaults to a boolean value. Now what does that mean? That means that the statement '"hello"' is not a boolean value. However, \[column]="hello" is a boolean value because it is either true or false for a given row.
You'll get an error if you try to use a non-boolean value in your 'When' condition.
You can use syntax, column references and parameters in your conditions and clauses. This is what makes the IF Column tool so powerful. See more in the [Syntax](/canvas/syntax) section.
Add a fallback syntax (else clause). All the rows that doesn't fulfill any of your conditions from Step #2 will get this value.
You can move conditions up and down in the list by clicking the up and down arrows to the right hand side of the configuration window. You can also delete individal conditions by clicking the "X" icon.
### Example: Working with boolean columns
In this example, we want to create a new column based on the value of a boolean column. See how we use ISFALSE syntax to catch false values - we could use ISTRUE syntax to catch true values.
### Example: Creating nulls
In this example, we want to create nulls if the value in our *int\_col* is lower than 500. Notice how we use the constant NULL (see [Syntax](/canvas/syntax)) in our 'Then' clause to create nulls.
### Example: More syntaxing
Now we're diving a bit deeper into syntaxing. Here we saying: "If the first character from the right of my *text\_col* is an '1' OR '2' OR '3' I want to create a new column with the value 'Catch this row, please'. If neither of those is true then I want to take the characters from 0 to 10 of my *format\_col* and make it uppercase.
### Example: Even more syntaxing!
Okay, now things are getting fun. We're adding two conditions below and using parameters in one of them. In the second condition we're also working with dates comparisons.
# New Column
Source: https://docs.less.tech/tools/new-columns/new-column
Create new columns
The New Column tool is one of the most versatile tools in Less. It allows you to create new columns based on the existing columns, static values, with syntax and using parameters.
It can be used for almost any use case you can think of.
### Configuration
Input a new column name.
It's in the field that you use syntax to create your new column. You can do a lot of different things with it: column reference, functions, operations, parameters and static values. Check out the examples below to see a couple of examples.
Note that if you create multiple new columns, you can reference the result of the previously added columns. Like this:
Notice how in the second column, we reference the *test* which was just created above. This is quite powerful, as you can chain multiple columns together and reduce the number of tools on your canvas.
### Example: Static Values
You can easily create new static values by using the syntax field. Here's a couple of examples for different types of columns. Notice the double-quotes around the text literal.
### Example: Conversion to date and date difference
You can easily convert a column to a date and use date difference with the syntax field. Here's an example of doing both simultaneously.
### Example: Coalesce and transforming to an integer
You can use coalesce to consolidate columns into a single column. It takes the first non-null value from the columns you specify.
In this example, row 2 and four in the *nulls\_col* column are null, so we then take the first character from the right of the *text\_col* and turn it into an interger. Finally, we mulitply it by 2000.
### Example: Working with parameters
You can also use [parameters](/tools/utilities/parameter) to create new columns. In the example below, we've done the following:
1. Created a parameter called *valueToDivideBy* and given it an integer value of 5
2. We use an IFF (conditional statement) function in the syntax
3. First we say, if the *nulls\_col* is null...
4. ...then give us the rounded *float\_col* to one decimal and divide it by our *valueToDivideBy* (which is 5 in this case)
5. ...otherwise, create a NULL value
Row to becomes 0 because *float\_col* is rounded to 0. Row 4 becomes 0.2 because *float\_col* is rounded to 1 and then divided by 5. The rest become null because the *nulls\_col* is not null.
# Parse Object
Source: https://docs.less.tech/tools/new-columns/parse-object
Parse Objects columns
The Parse Object tool is used exclusively to parse Object columns and is almost always used just after an [API](/tools/utilities/api) tool (and a [Columns](/tools/basics/columns) tool that turns the API response into an Object column).
Parsing objects can be tricky. It requires that you have more or less than same
structure throughout your column - which can be hard to spot with a lot
of data. Reach out to us if you'd like us to support.
The Parse Object tool transforms the below:
```json theme={null}
{ "name": "John", "age": 30, "car": null }
```
To columns like this:
Whenever you see this data type you can be certain you need to use the Parse Object tool.
However, object-like data can also be in simple text columns. Use a [Columns](/tools/basics/columns) tool to turn the text column into an Object column.
### Configuration
The Parse Object tool is very simple. All you have to do is select the Object column you want to parse.
### Examples
In this example, we have an Object column with the following data that contains name, age, city, address (which itself is an Object column with street and zip), gender and contact (which also is an Object column). We want to parse it into a new columns with the following data: name, age, city, street, zip, and country.
Notice that our original Object column is kept in the dataset. We can add additional Parse Object tools to parse the address and contact columns.
# Rank
Source: https://docs.less.tech/tools/new-columns/rank
Rank values in a column
The Rank tool allows you to assign ranks to values in a column using different ranking methods. This is particularly useful for creating leaderboards, percentiles, or ordering data.
### Configuration
Select the column you want to extract text from with Regex
The Regex tool will create a new column. Use this input to name it.
Choose how tied values should be ranked:
* **Average**: Tied values receive the average of the ranks they would have occupied. For example, if two values tie for 2nd and 3rd place, both get rank 2.5.
* **Ordinal**: Each value gets a unique rank based on its position in the original order, even if values are identical.
* **Competition/Minimum**: Tied values all receive the best (lowest) rank they would have gotten. For example, if two values tie for 2nd and 3rd place, both get rank 2.
* **Dense**: Similar to minimum ranking, but ranks are consecutive with no gaps. If two values tie for 2nd place, the next value gets rank 3 (not rank 4).
Here's an example of the different ranking methods:
Optionally group the ranking within categories defined by another column
# Regex
Source: https://docs.less.tech/tools/new-columns/regex
Extract text values in one or multiple columns
The Regex tool is a super-powered search-and-match tool, like "Find" in a text editor but much more flexible. It's a pattern-matching language that lets you describe what you're looking for rather than searching for exact text.
If you want to replace text values with regex, you can use the [Replace Text](/tools/basics/replace) tool.
To exemplify, you could use `(\d+)` to extract all the numbers from a column. Check out the examples at the end of the page for additional examples.
Regex (short for Regular Expressions) utilies a special language to extract certain elements of a text/string column.
### Configuration
The Regex tool consists of three required input.
Select the column(s) you want to extract text from with Regex
Input the regex statement you want to use. This can be a bit tricky, so we recommend you look at our examples below.
Remember to use capture groups (parentheses) around the parts of the regex you want to extract.
It can be helpful to use ChatGPT, Claude or Perplexity to help you with your regex statement.
As you add your capture groups, you'll see the option to rename the columns that will be created with the extracted values.
This might be neat to avoid using a [Columns](/tools/basics/columns) tool to rename the columns.
### Example: Decomposing a date
In this example, we want to separate the year, month, day and timestamp into separate columns with RegEx.
We use the following regex statement: `(\d+)-(\d+)-(\d+)\s(.+)`. To translate:
* `(\d+)-(\d+)-(\d+)`: This is the year, month and day.
* `\s`: This is the space between the date and the timestamp. We don't need this so we don't add a capture group.
* (.+)\`: This is the timestamp.
We then rename the capture group columns to `year`, `month`, `day` and `timestamp`.
### Example: Extracting numbers from a currency column
In this example, we want to extract the numbers from a currency column that contains currencies.
We use the following regex statement: `(\d+(?:\.\d+)?)`. To translate:
* `(\d+)`: This captures the main number part (one or more digits)
* `(?:\.\d+)?`: This is a non-capturing group that optionally matches a decimal point followed by one or more digits
* `(?:...)`: Non-capturing group (we don't want to extract the decimal part separately - non-capturing group means we don't want to store the decimal part separately but inside the same column)
* `\.`: Matches a literal dot (the decimal point)
* `\d+`: Matches one or more digits after the decimal
* `?`: Makes the entire decimal part optional (so it works for both "123" and "123.45")
This regex will extract the full number including decimals when present, but won't create separate columns for the decimal part.
# Row ID
Source: https://docs.less.tech/tools/new-columns/row-id
Create an ID column in your dataset
The Row ID is pleasantly simple. It creates a new column with a ID ranging from 1 to however many rows your data set contains. You can use a Group By functionality (see the configuration guide below) to create IDs within certain groups of your data.
## Configuration
However, you can choose to add IDs within groups.
Input the name of the column you want to create.
This is an optional input. Select the columns that you want to group by when creating IDs. The IDs will created inside each of these groups. In other words, if you group by a column, the IDs will start from 1 again for each group.
# Running Interval
Source: https://docs.less.tech/tools/new-columns/running-interval
Create custom running calculations
The Running Interval tool can be used to calculate custom running calculations. It can generate simple columns like 30 days running profit, but also other way cooler things like a custom customer acquisition cost metric.
If you're looking for more ways to do row-wise calculations check out the [Compare](/tools/new-columns/compare), [Cumulative](/tools/new-columns/cumulative), or [Loop](/tools/utilities/loop) tool.
### Configuration
The Running Interval tool will create a new column. Use this input to name it.
Select the column you want to use for a running interval calculation.
Input where you want your calculation to begin. Think of this as the row from your current row that your calculation should being. If you input -1 your calculation will always be calculated from your current row - 1 (understood vertically in your dataset).
Input how many rows you want to lookahead (or down in your dataset) from your offset. You can understand this and the previous input as creating a rolling range of data that you consider relevant.
Select how you want to aggregate the range that you have created with your offset and lookahead input. You can choose between sum, average, min, max, count, median and variance.
Select the columns you want to group by. This will create a running interval for each group.
### Example: Simple running sum
Here we have a very simple example where we want to calculate the running sum of our *simple\_int* column.
We want to go back 2 rows and look ahead 3 rows.
We use the following configuration:
We see that the first two rows are null because we don't have enough rows to lookback. The remaining 3 rows are calculated with this logic:
* Row 3: 1+2+3 = 6
* Row 4: 2+3+4 = 9
* Row 5: 3+4+5 = 12
### Example: 3-month rolling average revenue
In this example, we want to calculate the 3-month rolling average of revenue to get a more even revenue trend and remove the worst seasonality. We want the previous, the current and the next months to be included in the calculation.
In addition, we want to group by segment which in this case is a region (EU vs. US).
We use the following configuration:
Try looking at row 3 (Feb, 200, US, 200). Here we implicitly do the following:
* Exclude row 2 because it's the current month and because it's the same region (US).
* So we jump one additional row up until we find an observation within the same group. We include row 1 because it's the same region (US) and it then becomes our previous row/month.
* We include row 3 because it's the current month and because it's the same region (US).
* We skip row 4 because for the same reason as row 2.
* We include row 5 because it's the next month and because it's the same region (US).
Row 1 has a value of 100, row 3 has a value of 200 and row 5 has a value of 300 whereby our average is (100 + 200 + 300) / 3 = 200.
# Split Columns
Source: https://docs.less.tech/tools/new-columns/split-columns
Split text columns by delimiters
The Split Columns tool enables you to break apart a piece of text using a "marker" (delimiter) - like how you might cut a piece of paper where you see dotted lines.
The Split Columns tool can be highly customized. You can choose your delimiter, if you want to split to rows or columns, how many columns/splits you want and whether you want to split from left-to-right or right-to-left.
The Split Columns tool is very similar to the Text to Columns function in Excel
### Configuration
The Split Columns tool consists of three required input and two optional input.
Select the column you want to split.
Input the delimiter by which you want to split.
The delimiter is case-sensitive.
Select if you want to split to rows or columns.
This is an optional input. Select how many split you maximum want to create. This can be helpful if you data structure is not consistent and you want a particularly part of the content split.
This is an optional input. Select the direction to want to split - you can choose left-to-right or right-to-left.
Defaults to left-to-right.
### Example: I want to do something fun 🍌
Here you can see how you can split a column by a text delimiter into unlimited columns.
### Example: Getting the country from an address
Here we have a number of addresses that differ in the format and country. We're interested in the country.
If we split without a direction or max split, we would get the following result:
We see that we sometimes have country in the fourth column and sometimes in the fifth because of the differing format.
If we add a direction of right-to-left and set a max split of 1, we get the following result:
We see that we now have the country in the first new column and the rest of the address in the second new column.
### Example: Splitting line items to rows
Here we have a number of line items that are separated by a comma. We want to split these into rows.
We see that we now have separated the line items into rows.
# String to Date
Source: https://docs.less.tech/tools/new-columns/string-to-date
Turn weird date formats into date/datetime formats
The String to Date tool supports a quite narrow functionality. It is used to turn custom date column into date/datetime data formats. Generally Less is relatively good at autodetecting date formats with the [Columns](/tools/basics/columns), but sometimes date formats require manual parsing. That's where the String to Date tool is useful.
### Syntax
You tell Less how to parse your date by referring to certain formats. You can use the syntax below.
| Format | Description |
| ------ | ----------------------------- |
| `%Y` | Full year (e.g., 2001) |
| `%m` | Month number (01-12) |
| `%d` | Day of month (01-31) |
| `%B` | Full month name (e.g., July) |
| `%b` | Abbreviated month (e.g., Jul) |
| `%D` | Short date (MM/DD/YY) |
| `%F` | ISO date (YYYY-MM-DD) |
| `%v` | VMS date (DD-Mon-YYYY) |
| Format | Description |
| ------ | ------------------------------------ |
| `%H` | Hour in 24h format (00-23) |
| `%I` | Hour in 12h format (01-12) |
| `%M` | Minute (00-59) |
| `%S` | Second (00-60) |
| `%p` | AM/PM marker |
| `%R` | 24-hour time (HH:MM) |
| `%T` | 24-hour time with seconds (HH:MM:SS) |
| Format | Example |
| ------------------- | -------------------- |
| `%Y-%m-%d` | 2001-07-08 |
| `%d/%m/%Y` | 08/07/2001 |
| `%B %d, %Y` | July 08, 2001 |
| `%Y-%m-%d %H:%M:%S` | 2001-07-08 13:45:00 |
| `%d-%b-%Y %I:%M %p` | 08-Jul-2001 01:45 PM |
### Configuration
The String to Date tool consists of three required input.
Select the column with the date that you want to parse.
Input the name of the new column that will be created.
You can reference existing columns in the new column name if you want to overwrite the existing column.
Input the format of your date column using the syntax options above. Check out the example below to see how.
### Example: Parsing a date like 22 Aug 2025
Here we have a date column that is formatted as day, then short abbreviated month and then the year (22 Aug 2025). We want to parse this into a date/datetime data format.
# Group By
Source: https://docs.less.tech/tools/reshape/group-by
Separate data in groups and perform calculations within those groups
The Group By tool is one of the most used tools in Less. The Group By tool works by sorting data into boxes where each box represents a group. Once everything is in its box, you can count, total, or summarize what’s in each one. It’s a way to organize and analyze similar items together. To exemplify, "*group by customer\_type average session\_length*" could be translated to "*put my data in the customer\_type column groups and provide an average of the session length for those customer types*".
### Configuration
Select the column(s) to group by. You can input as many columns as you need. Adding more columns will make your groups/boxes more unique as the "boxes" become more specific.
This is technically an optional input. You don't have to greate any groups if you just want to.
Add your aggregation(s) pairs by selecting the column you want to aggregate and how you want to aggregate them.
You can choose to rename the output column if you want to.
You can choose from the following types of aggregations:
* **Sum**: summarize numeric values (numeric columns only)
* **Average**: find the average of numeric values (numeric columns only)
* **Min**: find the smallest numeric value (numeric and datetime columns only)
* **Max**: find the largest numeric value (numeric and datetime columns only)
* **Count**: count the occurances
* **Count Distinct**: count the unique occurances
* **First**: get the first value in the group
* **Last**: get the last value in the group
* **Concatenate**: get all your string values in a comma-separated cell (text columns only)
* **Standard Deviation**: find the standard deviation (numeric columns only)
* **Variance**: find the variance (numeric columns only)
* **Median**: find the median (numeric columns only)
* **Skewness**: find the skewness (numeric columns only)
* **Kurtosis**: find the kurtosis (numeric columns only)
You can move aggregations up and down by clicking the up and down arrows. You can also delete an aggregation by clicking the X icon.
You can add as many aggregations as you need. Click the *+ Add aggregation* button at the bottom of the configuration window to add more.
### Example: Without groups
In this example, we have a dataset with a number of different columns. We don't want to group by any columns, so we leave the "Group By" column(s) empty.
Note that we've renamed the columns to make them more readable in the output.
### Example: Two groups, counting and renaming
Here we have some questionaire data. We asked some respondents "What's your favorite analytics product?". We want to group by the question and answer and count the number of responses for each group.
Here you can see our data before we group by - notice that we have 3001 answers.
Here we've grouped by the *question* and *answer* columns and counted the number of responses for each group. We also renamed the output to *answerCount*
Evidently the results are quite clear...
### Example: First versus Minimum
There's a difference between the First and Minimum aggregations. The First aggregation gets the first value in the group, while the Minimum aggregation gets the smallest value in the group.
We have this dataset:
Below you can see the results of the First and Minimum aggregations.
As you can see, the First aggregation gets the first value, while the Minimum aggregation gets the smallest value. We didn't use any group by columns, so all the data is in the same group.
# Pivot
Source: https://docs.less.tech/tools/reshape/pivot
Convert rows to columns
Pivoting is like flipping your data to see it from a different perspective, making it easier to find patterns or trends. Imagine turning a list of daily sales into a "chart" where each date has its own row and each product becomes a column—it’s the same data but arranged differently. It’s all about reorganizing information so you can focus on the part that matters most for your analysis.
The Pivot tool more or less does the reverse of the [Transpose](/tools/reshape/transpose) tool
### Configuration
Select the column(s) to hold constant. You can imagine that the columns you select here will remain on rows.
Select the column you want to transform into columns. You can only select a single column.
Select the column you want to fill into the values of the column selection you made in Step #2. You can only select a single column.
Select how you want to aggregation your value column selection from Step #3.
You can choose from the following types of aggregations:
* **Sum**: summarize numeric values (numeric columns only)
* **Average**: find the average of numeric values (numeric columns only)
* **Min**: find the smallest numeric value (numeric and datetime columns only)
* **Max**: find the largest numeric value (numeric and datetime columns only)
* **Count**: count the occurances
* **Count Distinct**: count the unique occurances
* **First**: get the first value in the group
* **Last**: get the last value in the group
* **Concatenate**: get all your string values in a comma-separated cell (text columns only)
* **Standard Deviation**: find the standard deviation (numeric columns only)
* **Variance**: find the variance (numeric columns only)
* **Median**: find the median (numeric columns only)
* **Skewness**: find the skewness (numeric columns only)
* **Kurtosis**: find the kurtosis (numeric columns only)
### Example: The illustration example 👆
We want to pivot our data so our Metric row becomes columns and summarize the Value column per metric. We want to keep our Month constant
# Transpose
Source: https://docs.less.tech/tools/reshape/transpose
Convert columns to rows
The Transpose tool doesn't change your data, it simply reorganises it. It can help you restructure your data to reduce the need for additional tools.
The Transpose tool more or less does the reverse of the [Pivot](/tools/reshape/pivot) tool
The Transpose tool can be very useful before storing your data if you want to use filters/slicers in visualisation tools that select the metric instead of showing all metrics.
### Configuration
Select the column(s) to hold constant. You can imagine that the columns you select here will remain on rows.
Select the column you want to transform into columns. You can select as many columns as you need.
As these are transpose you will get a *Column* and *Value* column consisting of the selected columns name and corresponding value.
Select the column you want to transform into columns. You can select as many columns as you need.
As these are transpose you will get a *Column* and *Value* column consisting of the selected columns name and corresponding value.
Select the column you want to transform into columns. You can select as many columns as you need.
As these are transpose you will get a *Column* and *Value* column consisting of the selected columns name and corresponding value.
### Example: The illustration example 👆
# API
Source: https://docs.less.tech/tools/utilities/api
Call APIs from the Canvas
You can use the API tool for an almost unlimited amount of things. Trigger external actions, enrich your data with Large Language Models, send Slack messages, send data to other software tools or get data from other services.
The API tool is an advanced tool. You will call the API endpoint ones for every row in your data - so 10.000 rows = 10.000 API calls. **We strongly recommend testing on smaller datasets**.
**You are responsible** for respecting rate limits and general terms of use of whatever APIs that you are interacting with.
Reach out to us if you need support before using the API tool.
APIs are a method for computers to interact with each other (read more [here](https://zapier.com/resources/guides/apis/introduction)).
There are many types of API methods (GET, POST, PUT, DELETE, etc). You can think of this as different
way of interacting. A GET API call asks the other computer to return some data - you might call
Mailchimp's API to return all your campaigns with a GET call. PUT calls are used to update data - you might use a PUT call to update a member in Mailchimp. DELETE calls are used to delete data - you might use a DELETE call to delete a member in Mailchimp. POST calls asks the
other computer to generate something. For instance, you might use a POST call to ask OpenAI to
generate an AI review score. You could also use POST calls to create new members in Mailchimp.
You need to configure a couple of things when using API calls. In almost all methods, you need at least
three components:
1. **Method**. As discussed above; GET, POST, PUT, DELETE
2. **URL**. This describes what you want the computer do do (for instance GET `/lists/{list_id}/members`
to get all your members in the list corresponding to `list_id`)
3. **Authentication**. You need to inform the other computer who you are. Think of this as a key to opening
a door
### Configuration
You must accept our Terms of Use specifying that you are responsible for respecting rate limits and general terms of use of whatever APIs that you are interacting with.
Select the relevant API Method. You can choose between GET, POST, PUT, PATCH and DELETE.
Select the relevant body type. This can be either JSON, URL encoded or form data.
Input your JSON body. You can reference columns in your data like this. This means that for each row in your data, the API will be called with the value of the column in the row.
Input your URL. You can reference columns in your data like this. This means that for each row in your data, the API will be called with the value of the column in the row.
Add any relevant header key-value pairs. For instance, an *Authorization* header to authenticate your API call.
Add any relevant parameter key-value pairs.
Use these options to respect rate limits. You have four options:
* *Seconds between calls*: Wait a certain amount of time between each call. For instance, if you input *0.2* seconds, you will maximum call 5 calls per seconds.
* *Maximum calls per minute*: Call a maximum number of calls per minute. For instance, if you input *300* calls, you will call all 300 calls within the minute as fast as possible but no more than 300 calls per minute.
* *Stop after a number of requests*: Stop after a certain number of requests. For instance, if you input *1000* requests, you will call all 1000 requests as fast as possible but no more than 1000 requests.
* *Stop after a number of minutes*: Stop after a certain number of minutes. For instance, if you input *10* minutes, you will call all 10 minutes as fast as possible but no more than 10 minutes.
### When To Use
There are too many options with the API tool to list here, but generally you can use it to:
* Extract data with GET calls
* Send data with POST calls
* Update data with PUT calls
* Delete data with DELETE calls
# Comment
Source: https://docs.less.tech/tools/utilities/comment
Add documentation on the Canvas
The Comment tool is simple. It can be used to add documentation on the Canvas. Some use it to help colleagues understand workflows more easily while other use cases simply requires documentation.
You can do the following this in the Comment tool (top-left to bottom-right):
1. Large header text
2. Medium header text
3. Small header text
4. Paragraph text
5. Blockquote
6. Code-block
7. Bold text
8. Italic text
9. Strikethrough text
10. Underline text
11. Align text left
12. Align text center
13. Align text right
14. Align text justify
15. Adjust highlight text color
16. Change font color
17. Change background color
18. Add horizontal divider
19. Add image
You can drag the comment box with the hand icon on the left side of the comment box. You can adjust the size of the comment box with the resize icon on the bottom right of the comment box.
Note that you can also change the annotations of tools. Generally, we recommend using Comment tools to document multi-tool processes and the tool annotations to document single-tool logic.
# Describe
Source: https://docs.less.tech/tools/utilities/describe
Metadata about the dataset
The Describe tool is simple. Use it to get some quick information about the dataset you are working with.
The Describe tool doesn't require any configuration. It will give you the format, null count, mean, minimum, maximum and more for each column in your dataset.
# Directions
Source: https://docs.less.tech/tools/utilities/directions
Get distance, duration, and a route geometry between two points
The Directions tool computes a **driving-car** route between an origin and a destination, both defined by latitude and longitude columns on each row. It is intended to work together with tools like [Geocode](/tools/utilities/geocode) when you need coordinates from addresses first.
### What you get
For each row, the model adds (among others):
* **`geometry`** — route geometry stored as compressed TopoJSON.
* **`distance_meters`** and **`duration_seconds`** — summary distance and travel time from the routing response when the request succeeds.
* **`error`** / **`error_message`** — populated when the directions request fails, so you can filter or debug failed rows.
### Configuration
Numeric column for the start point latitude. You can pick a **column** or a **parameter** (parameters appear under their own section in the control).
Numeric column for the start point longitude. Columns or parameters, same as origin latitude.
Numeric column (or parameter) for the end point latitude.
Numeric column (or parameter) for the end point longitude.
All four fields are required. Null origin or destination coordinates on a row cause that run to fail with a clear error for that row.
# Flatten JSON
Source: https://docs.less.tech/tools/utilities/flatten-json
Flatten a JSON object into a table
The Flatten JSON tool should be used as a last resort when working with JSON data stored in Text columns.
It is much easier to use the Columns tool to convert JSON data into a an Object or List and then [Parse](/tools/new-columns/parse-object) or [Explode](/tools/new-columns/explode-list) the data into separate columns.
However, that is only possible if the JSON data schema is uniform. Sometimes, a JSON object has a nested structure where one row might contain a number and another row might contain an object. In that case, the Flatten JSON tool can be used to flatten the JSON object into a table.
With the Flatten JSON tool, all the JSON is parsed into a table with one row per JSON object. That means that the resulting table will be a rather long table with many rows.
Typically, you should use the [Split Columns](/tools/new-columns/split-columns) tool afterwards to separate the columns headers (and nested objects) into separate columns.
# Geocode
Source: https://docs.less.tech/tools/utilities/geocode
Get a GeoJSON Point and latitude/longitude from addresses or coordinates
The Geocode tool is part of the geospatial utilities, alongside [Directions](/tools/utilities/directions), [Polygon](/tools/utilities/polygon), and [Point-in-Polygon](/tools/utilities/point-in-polygon).
Use it when you need a consistent **GeoJSON Point** (and related fields) for downstream geospatial tools. It supports three modes:
1. **Forward geocoding** — street address, postal code, and country (optionally city and region) → coordinates and structured place fields.
2. **Reverse geocoding** — latitude and longitude → address-style properties and coordinates.
3. **Coordinates to GeoJSON** — numeric lat/lon columns → a `geometry` column with a Point struct only (no external geocoding call).
### Outputs (summary)
* **Forward** and **Reverse** append geocoding columns such as `geometry` (the GeoJSON point), `latitude`, `longitude`, structured fields (for example `street`, `locality`, `region`, `country`), and `geocode_error` when a row could not be resolved. With **max results** greater than 1, one input row can produce multiple output rows (one per matching feature).
* **Coordinates to GeoJSON** keeps your input columns and adds a `geometry` column: a GeoJSON Point `[longitude, latitude]`.
Choose **Address to coordinates (forward)**.
Select the string column that contains the street and street number (for example `Downing Street 10`). Only text columns are supported.
Select the string column that contains the postal code. Only text columns are supported.
Select the string column used to bias the search. Values must be [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3#Officially_assigned_code_elements) country codes (for example `USA`, `GBR`).
Optionally select a string column for the city or locality. Only text columns are supported.
Optionally select a string column for the region — first-level administrative divisions within countries, analogous to states in the US. Only text columns are supported.
Use the slider to choose between **1** and **10** matches to return per row. Higher values return more candidate features when the geocoder finds several matches.
Choose **Coordinates to address (reverse)**.
Pick the numeric columns for latitude and longitude (float columns).
Set **1–10** to cap how many reverse-geocode features are returned per input row.
Choose **Coordinates to GeoJSON (point)**.
Select the numeric columns that define each point. The tool builds a Point geometry from them; invalid or null pairs may yield null geometry for that row.
# Group
Source: https://docs.less.tech/tools/utilities/group
Containers to structure your Canvas
The Group tool is used to create a container for your other tools. This can be helpful to structure your Canvas and make it more readable.
You can change the name of the group to make it more descriptive.
# Loop
Source: https://docs.less.tech/tools/utilities/loop
Loop through the data until a condition is met
This tool is unstable and still in development
# Manual Input
Source: https://docs.less.tech/tools/utilities/manual-input
Create data on the Canvas
The Manual Input is a very simple spreadsheet directly on the Canvas. You can use it to create data directly on the Canvas instead of having to upload files.
The Manual Input tool can only create string/text columns. Use the [Columns](/tools/basics/columns.mdx) tool to change column formats.
It is helpful for a bunch of different use cases. For instance, writing mapping data directly on the Canvas before a [Combine](/tools/merge/combine), adding a reference date before an [Append](/tools/merge/append) and a lot of user use it in tandem with [API](/tools/utilities/api) tools to input a URL and some headers or parameter values.
# Parameter
Source: https://docs.less.tech/tools/utilities/parameter
A variable store for reusable values
Think of the Parameter tool as a *store* that holds one or multiple values you can use over and over again throughout your model. It can be very helpful to ensure consistency, flexibility, and organization in your model.
### Example
In the short video below, you can see that we created a Parameter called *numericValue* with a value of 100 (initially).
We then **reference** the *numericValue* in a [New Column](../new-columns/new-column) tool to multiply our *simple\_int* column with the value of the *numericValue* parameter.
Initially, we get a value of 100, 200, 300, etc. But if we change the value of the *numericValue* parameter to 500, we get a value of 500, 1000, 1500, etc.
You could have used the *numericValue* parameter in a 100 different tools. Changing it would then update all the values in the tools that reference it.
We recommend that you read more about [Parameters](/canvas/parameters) in the Canvas documentation.
# Point-in-Polygon
Source: https://docs.less.tech/tools/utilities/point-in-polygon
Test whether a GeoJSON point lies inside a TopoJSON polygon
Point-in-Polygon adds a boolean column that is **true** when the polygon’s **interior** contains the point and **false** otherwise. Points exactly on the boundary are not counted as inside. Use it after you have prepared compatible geometry columns — for example points from [Geocode](/tools/utilities/geocode) and polygons from [Polygon](/tools/utilities/polygon).
### Input expectations
* **Point column** — a Object column in **GeoJSON Point** form.
* **Polygon column** — a Object column holding **TopoJSON** polygon data
### Configuration
Choose the column that contains each GeoJSON Point.
Choose the column that contains each TopoJSON polygon to test against.
### Output
The tool appends a **`point_in_polygon`** boolean column with one value per input row.
# Polygon
Source: https://docs.less.tech/tools/utilities/polygon
Build polygons/area from coordinates or convert coordinate lists to polygons
The Polygon tool produces **polygons** in two different ways. Pair it with [Point-in-Polygon](/tools/utilities/point-in-polygon) or other workflows that expect a polygon column.
### Modes
1. **From coordinates** — start from a center latitude/longitude per row and call the isochrones service to build an area by **driving distance** or **driving time**.
2. **Convert from JSON** — start from a column of coordinate lists and close the ring to form a polygon without calling the isochrone API.
Select **From coordinates**.
Choose numeric columns for the center point of each polygon.
Pick **Distance** (kilometers) or **Time** (minutes) to control how large the polygons will be. For example, an area around a point with a 100 kilometer distance from the center point to the outer ring of the area is fairly. Conversely, a 5 minute drivetime distance from the center to the outer ring of the area is comparatively small.
Select range.
Distance can be between 1–100 kilometers. Time can between 1–180 minutes.
Adjust **0–100** to simplify or round the polygon boundary; higher values yield simpler, more rounded areas/polygons.
Select **Convert from JSON**.
Choose a **List** column where each row is an array of objects with **`lat`** and **`lon`** keys. The tool builds a TopoJSON polygon in the output **`geometry`** column.
### Outputs (summary)
* **From coordinates** — input columns are preserved where applicable; a **`geometry`** column holds the isochrone polygon (TopoJSON). Failed rows may include **`error`** and **`error_message`** fields.
* **Convert from JSON** — same row keys plus a **`geometry`** TopoJSON polygon per successful conversion.
# Relative Date
Source: https://docs.less.tech/tools/utilities/relative-date
Get the current date and time
The Relative Date tool lets you select a timezone and format and then return current date and time in that timezone. The tool is dynamic and will always return the date and time of when the tools is run - also when the models runs on a schedule.
### Configuration
The Today tool will create a new column. Use this input to name it.
Select the format that you want the current date and time to be formatted
in. You can choose between the following formats:
* *Now*: outputs the current date and time
* *Now (date)*: outputs the current date (at midnight, i.e. without the specific time)
* *Now (time)*: outputs the current time
* *Yesterday*: outputs the current datetime minus 1 day (i.e. yesterday at this specific time)
* *One week ago*: outputs the current datetime minus 1 day
* *One month ago*: outputs the current datetime minus 1 month
* *One year ago*: outputs the current datetime minus 1 year
Select the timezone that you want the current date and time to be formatted
in. All timezones are available in the dropdown.
### Example
In this example, we want a reference date that always references one week ago in GMT+01:00 (CET). Note the current date and time is 2025-09-25 19:54:00 in CET whereby we get a result of 2025-09-18 19:54:00 in CET.
# Validate
Source: https://docs.less.tech/tools/utilities/validate
Create customized warnings
The Validate tool is useful for automated testing and productionizing models. It enables you to create custom warnings based on conditions so you can highlight if something seems strange. The Validate tool can be highly effective for customizing warnings that highlight scenarios that should cause caution in the dataset.
You can create multiple warnings in a single model
### Configuration
There are two ways to use the Validate tool: zero rows and by condition. Zero rows means that you want to create a warning if the incoming dataset has zero rows. By condition means that you want to create a warning if a boolean column is false.
Select the method you want to use: zero row or by condition.
Info, Warning or Error. If an `Info` is triggered it will generate a row in your logs, a `Warning` will turn the whole job is to a warning and the `Error` will simply turn the job into an erroneous run.
If you choose Info or Warning in the log type, you can choose to stop the downstream execution. In other words, if you have tool attached after the Validate tool that you don't want to run, you should check this option.
Enter a message that you want to show in your logs. When using the "zero rows" method, you cannot reference columns. You can do that with the "by condition" method.
Select the method you want to use: zero row or by condition.
Info, warning or error
Select the timezone that you want the current date and time to be formatted
in. All timezones are available in the dropdown.
Select a Boolean column that will be used to trigger the validate tool. When the boolean column is `FALSE` then the validate tool will be triggered.
You can choose to stop the validation after one row that hits the FALSE value. Or print the first 10 rows in the job logs.
Enter a message that you want to show in your logs. You can reference columns, so you could write log messages comprising your data values (or at least the first 10 rows - see 'number of messages' above)
## Examples
In this case, we want to create a conditional warning when a our revenue column is lower than zero. That should be able to happen for our customers.
So we'll start by creating the boolean column that we'll use in the Validate tool.
Then we'll use that in our Validate tool. Notice the warnings in the bottom right-hand corner.
Lastly, when we run this demo model on a schedule, this is what we'll see in our job log. Notice how the warning messages are identical to the ones in the screenshot above.