# Baserow Appsmith Integration: REST API Setup Guide

> Build Appsmith screens on Baserow data via the free REST API - GET/POST/PATCH query patterns, a two-step file upload, and one token-authenticated Datasource.

Source: https://opennix.org/en/docs/baserow/integrations/appsmith-integration/


Appsmith builds custom admin panels, dashboards, and CRUD applications, and the open-source edition of Baserow serves as their relational data backend - the connection runs through one secured Datasource in Appsmith and a Baserow database token, and this guide covers setting up that datasource, the read and write query patterns, and a two-step file upload flow.

## Overview

A central **Datasource** is the bridge for the whole integration: every read, create, update, and delete query goes through the same secured connection in Appsmith, so the Baserow token never gets copied into individual queries by hand.

## Prerequisites

- **Baserow:** a [database (API) token](/docs/baserow/webhook-api/personal-api-tokens/) with `Create`, `Read`, `Update`, and `Delete` permissions.
- **Appsmith:** an account - Cloud or self-hosted.

## Step 1: Configure the Universal Datasource

Avoid hardcoding the API token into every query - use Appsmith's **Authenticated Datasource** feature to keep the token on the server and reuse it across the whole application.

1. In Appsmith, go to **Datasources** → **New Datasource** → **Authenticated API**.
2. **Name:** `Baserow API`.
3. **URL:** `https://api.baserow.io` (or the self-hosted instance URL).
4. **Authentication:**
   - **Type:** API Key.
   - **Key:** `Authorization`
   - **Value:** `Token [YOUR_DATABASE_TOKEN]` (keep a space between "Token" and the token value).
   - **Add To:** Header.
5. Click **Save**.

## Step 2: The Read Pattern (GET)

To populate a Table or List widget with data from Baserow:

1. Create a new query from the `Baserow API` datasource.
2. **Method:** `GET`
3. **Path:** `/api/database/rows/table/[TABLE_ID]/`
4. **Parameters:**
   - Key: `user_field_names` | Value: `true` (required, or fields come back as `field_123` instead of their names).
5. **Bind to Widget:** in the Table widget's **Table Data** property, enter `{{ get_rows.data.results }}`.

## Step 3: The Write Pattern (POST/PATCH)

Baserow uses `POST` to create rows and `PATCH` to update them.

### Create a Row (POST)

- **Path:** `/api/database/rows/table/[TABLE_ID]/`
- **Parameter:** `user_field_names` = `true`
- **Body (JSON):**

```json
{
  "Name": "{{ InputName.text }}",
  "Status": "{{ SelectStatus.selectedOptionValue }}",
  "Active": {{ CheckboxActive.isChecked }}
}
```

### Update a Row (PATCH)

Target the specific row ID.

- **Path:** `/api/database/rows/table/[TABLE_ID]/{{ Table1.triggeredRow.id }}/`
- **Body (JSON):** include only the fields that need to change.

```json
{
  "Status": "Archived"
}
```

## Step 4: The Two-Step File Upload Pattern

Baserow handles files differently from most simple APIs - a file cannot be sent directly to a row. It must first be **(1) uploaded** to the server, then **(2) linked** to the row.

### Action A: Upload the Binary (Helper Query)

Create a query named `upload_file`.

- **Method:** `POST`
- **Path:** `/api/user-files/upload-file/`
- **Headers:** `Content-Type`: `multipart/form-data`
- **Body:** Form Data
  - Key: `file` | Type: `File` | Value: `{{ FilePicker1.files[0] }}`

*Response:* Baserow returns a `name` hash (for example, `"abcd-1234-image.png"`).

### Action B: Link to the Row (Main Query)

Create a query named `link_file_to_row`.

- **Method:** `PATCH`
- **Path:** `/api/database/rows/table/[TABLE_ID]/{{ Table1.selectedRow.id }}/`
- **Body (JSON):**

```json
{
  "Documents": [
    {
      "name": "{{ upload_file.data.name }}"
    }
  ]
}
```

### Workflow Logic

On the **FilePicker** widget, set the **onFilesSelected** event to run a JS object:

```javascript
export default {
  async handleUpload() {
    // 1. Upload the file to Baserow storage
    await upload_file.run();

    // 2. Link the new file hash to the target row
    await link_file_to_row.run();

    // 3. Refresh the table to show the new file
    await get_rows.run();
  }
}
```

## Best Practices

- **Pagination.** Enable Server Side Pagination on the Appsmith Table widget and pass `&page={{Table1.pageNo}}` to the Baserow GET query - this keeps large tables fast to load.
- **Select fields.** If the Baserow table has a [single select field](/docs/baserow/field-types/single-select-field/), creating a row through the API requires the exact option text (case-sensitive) or the option's numeric ID.

## Frequently Asked Questions

**Do I need a separate automation service between Appsmith and Baserow?** No - both the read and write patterns run directly on the [Baserow database REST API](/docs/baserow/webhook-api/database-api/) and a single Appsmith Datasource; a middleware service can be added, but it is not required.

**What happens if a file is sent along with the other row fields in one request?** Nothing gets saved - Baserow only accepts files through the dedicated upload endpoint, so the create or update request always runs after the file has already been uploaded and its hash retrieved.

**How should a large Baserow table be handled in an Appsmith list or table?** Use the GET query's `page` parameter together with the widget's server-side pagination - Appsmith then requests rows page by page instead of loading the whole table at once.

Related reading: [database (API) tokens](/docs/baserow/webhook-api/personal-api-tokens/) for scoping what a third-party app can reach, and the [Baserow REST API overview](/docs/baserow/webhook-api/database-api/) for the full list of endpoints for reading, writing, and deleting rows.

