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.

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_client_id}}

Returns all matching rows as array.

Table ID (Required)

Table ID: 15

The ID of the custom table to query. Find in CRM under 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_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.

Syntax: - row_col_X where X is column number - Column 1 is first custom column (after default fields) - Supports exact matching - Supports blank value matching

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_client_id}}
row_col_1: Active
row_col_2: Enterprise
row_col_3: EMEA

Blank Value Matching

row_col_7: 

Empty value matches blank/null fields.

Use case: Find records with missing data:

row_col_5:
# Finds rows where column 5 is blank

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.

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

Example 1: Customer Preferences Lookup

Scenario: Fetch customer communication preferences before sending campaign email

Table Structure:

Table 18 - Communication Preferences
Column 1: Email Frequency (Daily/Weekly/Monthly)
Column 2: Topics of Interest
Column 3: Preferred Contact Time
Column 4: SMS Opt-In (Yes/No)
Column 5: Language Preference

Workflow: 1. Schedule Trigger - Weekly campaign 2. MySQL Query - Get active customers 3. Loop - For each customer 4. Match to Client - Get client record 5. Table Task - Fetch preferences 6. If Task - Check email frequency 7. Email - Send personalized campaign

Fetch Preferences:

Action: fetch_row
Table ID: 18
Client ID: {{task_15001_client_id}}

Check Campaign Eligibility:

If: {{task_25001_data.*.col_1}} = Weekly OR Monthly
And: Last campaign was > 7 days ago
Then: Send campaign

Personalized Email:

To: {{task_15001_email}}
Subject: {{task_25001_data.*.col_5}} - Weekly Industry Update

Hi {{task_15001_first_name}},

Based on your interest in {{task_25001_data.*.col_2}}, here are this week's highlights...

Best time to reach you: {{task_25001_data.*.col_3}}

[Unsubscribe] [Update Preferences]

Example 2: Dynamic Pricing Lookup

Scenario: Quote generator fetches client-specific pricing from custom table

Table Structure:

Table 22 - Client Pricing
Column 1: Product Category
Column 2: Plan Type (Standard/Premium/Enterprise)
Column 3: Monthly Price
Column 4: Annual Price
Column 5: Setup Fee
Column 6: Discount %
Column 7: Valid Until

Workflow: 1. Form Submission - Quote request 2. Match to Client - Find customer 3. Table Task - Get pricing tier 4. Code Task - Calculate totals with discount 5. PDF Task - Generate quote document 6. Email - Send quote

Get Client Pricing:

Action: fetch_row
Table ID: 22
Client ID: {{task_15001_client_id}}
row_col_1: {{task_55001_product_category}}
row_col_2: {{task_55001_plan_type}}

Calculate Total:

const monthlyPrice = parseFloat(input.task_25001_data['*'].col_3);
const annualPrice = parseFloat(input.task_25001_data['*'].col_4);
const setupFee = parseFloat(input.task_25001_data['*'].col_5);
const discount = parseFloat(input.task_25001_data['*'].col_6);
const quantity = parseInt(input.task_55001_quantity);

const billingCycle = input.task_55001_billing; // monthly or annual
const basePrice = billingCycle === 'annual' ? annualPrice : monthlyPrice;

const subtotal = basePrice * quantity;
const discountAmount = subtotal * (discount / 100);
const total = (subtotal - discountAmount) + setupFee;

return {
  subtotal: subtotal.toFixed(2),
  discount_amount: discountAmount.toFixed(2),
  setup_fee: setupFee.toFixed(2),
  total: total.toFixed(2),
  unit_price: basePrice.toFixed(2),
  discount_pct: discount
};

Quote Email:

Subject: Your Custom Quote for {{task_55001_product_category}}

Dear {{task_15001_full_name}},

Thank you for your interest in our {{task_55001_plan_type}} plan.

Quote Summary:
Product: {{task_55001_product_category}}
Plan: {{task_55001_plan_type}}
Quantity: {{task_55001_quantity}} licenses
Unit Price: ${{task_42001_unit_price}}

Subtotal: ${{task_42001_subtotal}}
Discount ({{task_42001_discount_pct}}%): -${{task_42001_discount_amount}}
Setup Fee: ${{task_42001_setup_fee}}
TOTAL: ${{task_42001_total}}

Valid until: {{task_25001_data.*.col_7}}

[View Full Quote PDF] [Accept Quote]

Example 3: Territory Assignment Lookup

Scenario: Route leads to correct sales rep based on territory table

Table Structure:

Table 8 - Sales Territories
Column 1: Country
Column 2: State/Province
Column 3: City (optional)
Column 4: Sales Rep (Type 17 - User multi-select)
Column 5: Manager
Column 6: Territory Code
Column 7: Support Level

Workflow: 1. Webhook In - New lead from ad platform 2. Phone Formatter - Format phone number 3. Table Task - Find territory 4. Coalesce - Fallback to default rep 5. New Client - Create lead 6. Workflow Note - Assign to rep 7. Email - Alert rep

Find Territory by State:

Action: fetch_row
Table ID: 8
row_col_1: {{task_46001_country}}
row_col_2: {{task_46001_state}}

Fallback to Default Rep:

Values to check:
1. {{task_25001_data.*.col_4}}
2. sales-default@company.com

Create Lead:

Company Name: {{task_46001_company}} {{task_46001_full_name}}
Status: New Lead
Responsible Manager: {{task_19001_value}}

Contact:
First Name: {{task_46001_first_name}}
Surname: {{task_46001_last_name}}
Email: {{task_46001_email}}
Cell: {{task_7001_formatted}}

Assign Task:

Type: Call
Client ID: {{task_13001_client_id}}
Due: today
Priority: High
User Tags: {{task_19001_value}}, {{task_25001_data.*.col_5}}

Note: New {{task_25001_data.*.col_6}} Territory Lead

Lead: {{task_46001_full_name}} ({{task_46001_company}})
Location: {{task_46001_city}}, {{task_46001_state}}, {{task_46001_country}}
Phone: {{task_7001_formatted}}
Email: {{task_46001_email}}

Source: {{task_46001_utm_source}}
Campaign: {{task_46001_utm_campaign}}

Support Level: {{task_25001_data.*.col_7}}

Scenario: Get product details from catalog for order processing

Table Structure:

Table 31 - Product Catalog
Column 1: SKU
Column 2: Product Name
Column 3: Category
Column 4: Price
Column 5: Stock Status
Column 6: Supplier
Column 7: Lead Time Days
Column 8: Product URL

Workflow: 1. Form Submission - Product inquiry 2. Match to Client - Find customer 3. Table Task - Get product details 4. If Task - Check stock status 5. AI Prompt - Generate product recommendation 6. Email - Send product info

Get Product by SKU:

Action: fetch_row
Table ID: 31
row_col_1: {{task_55001_product_sku}}

Check Stock:

Condition: {{task_25001_data.*.col_5}} = In Stock
True: Process immediately
False: Check lead time and notify

Product Info Email (In Stock):

Subject: {{task_25001_data.*.col_2}} - Product Information

Hi {{task_15001_first_name}},

Thank you for your inquiry about {{task_25001_data.*.col_2}}.

Product Details:
SKU: {{task_25001_data.*.col_1}}
Name: {{task_25001_data.*.col_2}}
Category: {{task_25001_data.*.col_3}}
Price: ${{task_25001_data.*.col_4}}
Status: {{task_25001_data.*.col_5}} ✓

This product is currently in stock and ready to ship!

[View Product] [Add to Cart] [Request Quote]
{{task_25001_data.*.col_8}}

Product Info Email (Back Order):

Subject: {{task_25001_data.*.col_2}} - Stock Update

Hi {{task_15001_first_name}},

Thank you for your interest in {{task_25001_data.*.col_2}}.

Product Details:
SKU: {{task_25001_data.*.col_1}}
Price: ${{task_25001_data.*.col_4}}
Status: {{task_25001_data.*.col_5}}

Expected availability: {{task_25001_data.*.col_7}} days
Supplier: {{task_25001_data.*.col_6}}

Would you like to:
- Pre-order now (ships when available)
- View similar in-stock products
- Get notified when available

[Pre-Order] [View Alternatives] [Notify Me]

Example 5: Support Ticket History Lookup

Scenario: Fetch previous support interactions before creating new ticket

Table Structure:

Table 42 - Support History
Column 1: Ticket Type
Column 2: Priority
Column 3: Status
Column 4: Assigned Agent
Column 5: Resolution Summary
Column 6: Resolution Time Hours
Column 7: Customer Satisfaction

Workflow: 1. Email Trigger - Support email received 2. Match to Client - Find customer 3. Table Task - Get ticket history (all rows) 4. Code Task - Analyze history 5. Workflow Note - Create ticket with context 6. If Task - Check if VIP customer 7. Email - Acknowledgment

Get All Customer Tickets:

Action: fetch_all_rows
Table ID: 42
Client ID: {{task_15001_client_id}}

Analyze Support History:

const tickets = input.task_25001_data;
let totalTickets = 0;
let openTickets = 0;
let avgResolutionTime = 0;
let avgSatisfaction = 0;
let recentIssues = [];

for (const rowId in tickets) {
  const ticket = tickets[rowId];
  totalTickets++;

  if (ticket.col_3 === 'Open' || ticket.col_3 === 'In Progress') {
    openTickets++;
  }

  const resTime = parseFloat(ticket.col_6) || 0;
  avgResolutionTime += resTime;

  const satisfaction = parseFloat(ticket.col_7) || 0;
  avgSatisfaction += satisfaction;

  // Track recent issues
  recentIssues.push({
    type: ticket.col_1,
    resolution: ticket.col_5,
    date: ticket.created
  });
}

avgResolutionTime = totalTickets > 0 ? (avgResolutionTime / totalTickets).toFixed(1) : 0;
avgSatisfaction = totalTickets > 0 ? (avgSatisfaction / totalTickets).toFixed(1) : 0;

// Sort recent issues by date, limit to 3 most recent
recentIssues.sort((a, b) => new Date(b.date) - new Date(a.date));
recentIssues = recentIssues.slice(0, 3);

return {
  total_tickets: totalTickets,
  open_tickets: openTickets,
  avg_resolution_hours: avgResolutionTime,
  avg_satisfaction: avgSatisfaction,
  recent_issues: JSON.stringify(recentIssues),
  is_frequent: totalTickets >= 10,
  has_open_tickets: openTickets > 0
};

Create Ticket with Context:

Type: To-Do
Client ID: {{task_15001_client_id}}
Due: today
Priority: High
User Tags: support-team@company.com

Note: New Support Request - {{task_15001_company_name}}

From: {{task_2001_from_email}}
Subject: {{task_2001_subject}}

Customer Profile:
Total Tickets: {{task_42001_total_tickets}}
Open Tickets: {{task_42001_open_tickets}}
Avg Resolution: {{task_42001_avg_resolution_hours}} hours
Satisfaction: {{task_42001_avg_satisfaction}}/5 ⭐

Recent Issues:
{{task_42001_recent_issues}}

Current Request:
{{task_2001_body}}

⚠️ {{task_42001_is_frequent}} = True: Frequent support user
⚠️ {{task_42001_has_open_tickets}} = True: Has open tickets

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: Filter for blank value doesn't work

Cause: Column contains whitespace or null

Solution: - Use Code task to normalize data - Check actual value in table - May need row_col_X: with empty value

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 Task - Process and transform table data
  • Loop - Iterate through multiple rows
  • If Task - Conditional logic based on table data
  • Coalesce - Provide fallback values
  • Variable - Store frequently used table values