Build internal tools with Appsmith low-code frontend

Appsmith allows you to build custom admin panels, dashboards, and CRUD apps. Baserow acts as the relational database backend. By connecting them via API, you can build tools that follow your exact business logic without exposing the raw database to end-users.

We configure a central Datasource that acts as the bridge. All queries (Read, Write, Delete) use this single secure connection.

Prerequisites

  • Baserow: A Database Token with Create, Read, Update, and Delete permissions.
  • Appsmith: An account (Cloud or Self-Hosted).

Step 1: Configure the Universal Datasource

Do not hardcode your API token into every individual query. Use Appsmith’s Authenticated Datasource feature. This keeps your token on the server and makes it reusable across the entire application.

  1. In Appsmith, go to Datasources -> New Datasource -> Authenticated API.
  2. Name: Baserow API.
  3. URL: https://api.baserow.io (or your self-hosted URL).
  4. Authentication:
    • Type: API Key.
    • Key: Authorization
    • Value: Token [YOUR_DATABASE_TOKEN] (Ensure there is a space between “Token” and the key).
    • Add To: Header.
  5. Click Save.

Step 2: The “Read” Pattern (GET)

To populate a Table or List widget, fetching 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 (Crucial for using “Name” instead of “field_123”).
  5. Bind to Widget: In your Table Widget’s Table Data property, enter {{ get_rows.data.results }}.

Step 3: The “Write” Pattern (POST/PATCH)

Baserow uses POST to create and PATCH to update.

Create (POST)

  • Path: /api/database/rows/table/[TABLE_ID]/

  • Parameter: user_field_names = true

  • Body (JSON):

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

Update (PATCH)

You must target the specific Row ID.

  • Path: /api/database/rows/table/[TABLE_ID]/{{ Table1.triggeredRow.id }}/

  • Body (JSON): Only include the fields you want to change.JSON

    {
      "Status": "Archived"
    }
    

Step 4: The “Two-Step” File Upload Pattern

Baserow handles files differently than many simple APIs. You cannot send a file directly to a row. You must (1) Upload the file to the server, then (2) Link it to the row.

Action A: Upload Binary (The 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 (e.g., returns: "abcd-1234-image.png").

Create a query named link_file_to_row.

  • Method: PATCH

  • Path: /api/database/rows/table/[TABLE_ID]/{{ Table1.selectedRow.id }}/

  • Body (JSON):

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

Workflow Logic

In your FilePicker Widget, set the onFilesSelected event to run a JavaScript Object:

export default {
  async handleUpload() {
    // 1. Upload the file to Baserow storage
    await upload_file.run();
    
    // 2. Link the new file hash to the actual 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” in the Appsmith Table widget. Pass &page={{Table1.pageNo}} to the Baserow GET query to handle large datasets efficiently.
  • Dropdowns: If your Baserow table has a “Single Select” field, creating a row via API requires the exact text value (case-sensitive) or the numeric Option ID.

Still need help? If you’re looking for something else, please feel free to make recommendations or ask us questions; we’re ready to assist you.