Skip to content

Table Task

Overview

The Table Task fetches and searches data from custom tables in your CRM. Use it to query configuration data, lookup values, retrieve customer preferences, search product catalogs, or access any structured data you've stored in custom tables.

The tables are the ones people see and fill in on a client's Tables tab — see Custom tables. A row this task adds appears there straight away, and to start a workflow when someone adds or changes a row there, use a CRM Trigger.

When to use this task:

  • Lookup customer preferences or settings
  • Query product catalogs or pricing
  • Retrieve configuration values
  • Search inventory or stock data
  • Access project history
  • Fetch support ticket information
  • Get custom field mappings
  • Retrieve territory assignments

Key Features:

  • Fetch single row or all rows
  • Search by row ID
  • Filter by client ID and column values
  • Support for multiple filter conditions
  • Returns latest matching row if multiple found
  • Handles blank/empty values
  • Works with user multi-select fields
  • Structured output by row and column

Quick Start

Fetch Single Row:

1. Add Table task
2. Select Action: Fetch Row
3. Enter Table ID
4. Set Row ID
5. Save

Fetch by Client + Filters:

1. Add Table task
2. Select Action: Fetch Row
3. Enter Table ID
4. Set Client ID
5. Add column filters (row_col_X)
6. Save

Fetch All Rows:

1. Add Table task
2. Select Action: Fetch All Rows
3. Enter Table ID
4. Set Client ID (optional)
5. Add filters (optional)
6. Save

Configuration

Action Selection

Fetch Single Row:

Action: fetch_row
Table ID: 15
Row ID: {{task_43001_preference_row_id}}

Returns single matching row.

Fetch All Rows:

Action: fetch_all_rows
Table ID: 15
Client ID: {{task_15001_match_client_id}}

Returns the IDs of all matching rows in row_ids.

Return row data (fetch_all_rows only)

Off by default. Tick Return row data to also get the values of the matching rows in rows, each shaped like the table output of Fetch Row, ready for a Loop.

rows holds the first 100 rows only, lowest row ID first. row_ids still lists every match, so you can tell when there were more than 100. Match to Clients and the Contact task's Get Contacts have the same box for clients and contacts.

Table ID (Required)

Table ID: 15

The custom table to query. In the task builder, pick it by name from the Table list; the task stores its ID. Tables are set up on a client's Tables tab — see Custom tables.

Row ID (fetch_row only)

Row ID: 12345
Row ID: {{task_43001_row_id}}

Direct row lookup by ID. Fastest method if you know the row ID.

When to use:

  • Previous task returned row ID
  • Direct record access needed
  • No filtering required

Client ID

Client ID: {{task_15001_match_client_id}}

Optional for fetch_row with row_id, required for client_id_columns search method.

When to use:

  • Fetch customer-specific data
  • Filter by client ownership
  • Get client preferences/settings

Column Filters (row_col_X)

row_col_5: Active
row_col_8: Enterprise
row_col_12: {{task_55001_product_category}}

Filter by column values. Column numbers match your table structure.

In the task settings, use + Add filter to add only the columns you want to filter on; with no filters, Fetch Row returns the client's newest row and Fetch All Rows returns all of them. Edit Row works the same way with + Add column: only the listed columns are changed, and a listed column left blank is emptied.

Syntax:

  • row_col_X where X is column number
  • Column 1 is first custom column (after default fields)
  • Supports exact matching
  • Can match an empty cell, or any value, with the column's condition (see below)

Example table structure:

Table 15 - Customer Preferences
Column 1 (row_col_1): Status
Column 2 (row_col_2): Plan Type
Column 3 (row_col_3): Region
Column 4 (row_col_4): Language
Column 5 (row_col_5): Preferences (JSON)

Filter for active enterprise customers in EMEA:

Table ID: 15
Client ID: {{task_15001_match_client_id}}
row_col_1: Active
row_col_2: Enterprise
row_col_3: EMEA

Blank Filters

row_col_7:

An empty filter is ignored — it does not filter on that column. This is also what happens when a filter is a variable that turned out empty.

Between each filter's column and its value there is a small button reading Matches, so the row reads as a sentence. Click it and it steps to the next way of matching, and round again at the end:

The button reads Rows kept
Matches The cell equals the value (blank value = no filter). On a single select column, any of the options you pick
Does not match The cell is anything else, blank included (blank value = no filter). On a single select column, none of the options you pick
Contains The value appears anywhere in the cell. Capital letters make no difference: paid finds Paid in full and Unpaid
Does not contain The value appears nowhere in the cell, blank included
Is empty The cell is blank, never filled in, or a multi-select with nothing picked. No value is needed
Has any value The cell holds something. No value is needed

Contains and Does not contain are offered on Single-Line Text and Multi-Line Text columns only. Other column types are matched whole, because part of an option, a date or a number would mean nothing.

On a single select column a filter can tick several options: with Matches a row holding any of them is kept, with Does not match only rows holding none of them. In Variable mode, give the option IDs separated by commas. A multi select column is still compared as the whole list you give it.

The same button, with the same choices and wording, is on Match to Clients and on the Contact task's matching items.

Each filter is stored as two settings: the value under row_col_<column id>, and how it is matched under match_col_<column id>, holding not_equals, contains, not_contains, empty or not_empty (blank for Matches).

Checkbox columns don't have a condition — filter them with Yes or No.

Date Fields

Filter syntax:

row_col_4: 21/09/2026
row_col_4: 2026-09-21

Either format matches. Fetch Row outputs dates as DD/MM/YYYY, so a fetched date can be passed straight into a later filter. A value that isn't a valid date matches no rows.

User Multi-Select Fields

Custom tables support multi-select user fields.

Filter syntax:

row_col_9: user@company.com

Matches if user is in the multi-select list.

Outputs

Field Type Example Notes
table array [{"id":1,…}] The rows returned. Iterate with a Loop using action set to array.
table_row_id number 4471 The row acted on, for single-row actions.
row_ids string 4471,4472 Fetch All Rows: comma-separated IDs of every matching row.
rows array [{"row_id":4471,…}] Fetch All Rows with Return row data ticked: the first 100 matching rows, each with table_id, label, client_id, row_id, row (its cells, as in table) and row_link.
run boolean true
run_text string Table data retrieved.

Output Structure

Single Row Output

{
  "task_25001_data": {
    "12345": {
      "row_id": "12345",
      "client_id": "67890",
      "col_1": "Active",
      "col_2": "Enterprise",
      "col_3": "EMEA",
      "col_4": "English",
      "col_5": "{\"email_freq\": \"daily\", \"sms_opt_in\": true}",
      "created": "2025-01-15 10:30:00",
      "updated": "2026-02-01 14:22:00"
    }
  }
}

Access fields:

  • Row ID: {{task_25001_data.12345.row_id}}
  • Column 1: {{task_25001_data.12345.col_1}}
  • Column 2: {{task_25001_data.12345.col_2}}
  • Created: {{task_25001_data.12345.created}}

Multiple Rows Output

{
  "task_25001_data": {
    "12345": {
      "row_id": "12345",
      "client_id": "67890",
      "col_1": "Active",
      "col_2": "Enterprise"
    },
    "12346": {
      "row_id": "12346",
      "client_id": "67890",
      "col_1": "Active",
      "col_2": "Professional"
    }
  }
}

Access specific row:

  • {{task_25001_data.12345.col_1}}
  • {{task_25001_data.12346.col_2}}

Loop through all rows:

Use Loop task with {{task_25001_data}}
Access: {{task_29001_item.value.col_1}}

Real-World Examples

Look up a stored setting for a client

CRM Trigger
  └─ Table       fetch_row by client and column
      └─ Email   use the value from {{task_25001_table}}

Record a row against a client

Form Submission
  └─ Match to Client   look the client up
      └─ Table         add_row with the submitted details

{{task_25001_table_row_id}} is the row that was written, which you need if a later task edits it.

Work through a table's rows

Schedule
  └─ Table       fetch_all_rows
      └─ Loop    over {{task_25001_table}}, action: array

Tables hold rows, not answers

The task reads and writes individual rows. It does not total, count or group them — for that, see MySQL Query.

Best Practices

Table Design

  1. Use consistent column types - Don't mix data formats in same column
  2. Index frequently searched columns - Improves performance
  3. Keep column count reasonable - Max 20 columns per table
  4. Use descriptive column names - Document in CRM
  5. Maintain data quality - Regular cleanup and validation

Search Strategy

  1. Use row_id when available - Fastest lookup method
  2. Combine client_id with columns - Efficient filtering
  3. Limit filter columns - Only necessary conditions
  4. Handle missing data - Check for blank values
  5. Consider fetch_all vs fetch_row - Based on expected results

Performance

  1. Don't fetch unnecessary data - Use filters
  2. Cache frequently accessed data - Store in variables
  3. Batch operations - Use loops efficiently
  4. Monitor table size - Archive old data
  5. Index key columns - Improves query speed

Data Handling

  1. Validate table output exists - Use If task to check
  2. Handle multiple row IDs - When using * wildcard
  3. Parse JSON columns - Use Code task for complex data
  4. Format dates and numbers - Use formatter tasks
  5. Provide fallbacks - Use Coalesce for missing data

Troubleshooting

No Data Returned

Issue: Table task returns empty

Causes:

  • Invalid table ID
  • No matching rows
  • Incorrect filter values
  • Wrong column numbers
  • Client ID mismatch

Solution:

  1. Verify table ID in CRM
  2. Check filter values match exactly (case-sensitive)
  3. Confirm column numbers (col_1 is first custom column)
  4. Test with fewer filters
  5. Use fetch_all_rows to see all data

Wrong Row Returned

Issue: Returns unexpected row

Cause: Multiple rows match filters, returns latest

Solution:

  • Add more specific filters
  • Use unique identifier (row_id) if known
  • Check table for duplicate data
  • Review column values in CRM

Cannot Access Column Data

Issue: {{task_25001_data.*.col_X}} returns empty

Causes:

  • Wrong row ID in path
  • Column doesn't exist
  • Using * with multiple rows

Solution:

# Single row - use *:
{{task_25001_data.*.col_1}}

# Specific row ID:
{{task_25001_data.12345.col_1}}

# Multiple rows - use Loop task:
Loop over {{task_25001_data}}
Access: {{task_29001_item.value.col_1}}

Blank Value Not Matching

Issue: Leaving a filter blank returns rows that have a value in that column

Cause: A blank filter means "don't filter on this column"

Solution: Set the column's condition to Is empty. Cells holding only spaces count as empty.

Performance Slow

Issue: Table lookup takes long time

Causes:

  • Large table (1000+ rows)
  • Complex filters on multiple columns
  • Unindexed columns

Solution:

  • Use row_id lookup when possible
  • Reduce filter complexity
  • Archive old data
  • Contact admin about indexing

Frequently Asked Questions

Can I update table data?

No, this task only reads data. Update manually in CRM or use API.

Can I search multiple tables?

No, one table per task. Use multiple Table tasks for multiple tables.

What's the maximum table size?

Recommended under 10,000 rows. Performance degrades with very large tables.

Can I join tables?

No, tables are independent. Fetch from each separately and join in Code task.

How do I handle multiple matching rows?

Use fetch_all_rows action and loop through results, or add more filters to get single row.

Can I filter by date range?

No direct date range filter. Fetch all rows and filter in Code task.

Do I need exact column value match?

Yes, filters are exact match only. Use Code task for partial matching or regex.

Can I sort results?

No built-in sorting. Use Code task to sort after fetching.


  • Match to Client - Get client ID for table queries
  • MySQL Query - Query database directly for complex needs
  • Code - Process and transform table data
  • Loop - Iterate through multiple rows
  • If Statement - Conditional logic based on table data
  • Coalesce - Provide fallback values
  • Variable - Store frequently used table values