Smart Columns
Smart columns process data per row. AI columns run prompts, HTTP columns call APIs, formula columns compute values, integration columns push data, lookup columns join across tables. The table IS the workflow.
Template Variables
Use {{column_name}} in prompts, URLs, request bodies, and run conditions to reference other columns in the same row. When the smart column runs, each {{...}} placeholder is replaced with the actual value from that row.
| Syntax | Description | Example |
|---|---|---|
{{column_name}} | Value of a column in the current row | {{country}} -> "France" |
{{column.nested_field}} | Nested field from a JSON column | {{company_data.industry}} -> "SaaS" |
{{column.arr[0]}} | Array index from a JSON column | {{metadata.tags[0]}} -> "enterprise" |
What is the capital of {{country}}?
Reply with ONLY the city name.{
"contents": [{
"parts": [{
"text": "Classify {{company}} ({{website}}) by industry. One word."
}]
}]
}Column Kinds
Every smart column has a kind that determines what it does when processing a row. There are 5 kinds:
| Kind | What It Does | Config Keys | Rate Limited |
|---|---|---|---|
ai | Runs an AI prompt per row using built-in models | prompt, model, max_tokens, temperature | Yes |
http | Makes an HTTP request per row, extracts response data | url, method, headers, body, extract | Yes |
formula | Computes a value from other columns in the same row | expression | No |
integration | Pushes row data to an external service (webhook, Slack, etc.) | target, url, method, headers, body | Yes |
lookup | Cross-table VLOOKUP -- joins data from another table | source_table, match_column, return_column | No |
hypertab_add_smart_column
/api/tables/:tableId/smart-columnshypertab_add_smart_columnAdd a smart column that processes data per row. AI columns run prompts, HTTP columns call APIs, formula columns compute values, integration columns push data, lookup columns join across tables.
| Parameter | Type | Description |
|---|---|---|
tablerequired | string | Table name or ID |
namerequired | string | Column name (lowercase, underscores, must start with a letter). Max 64 chars. |
typerequired | string | Output data type: text, number, json, boolean, email, url, phone, datetime, select, multi_select, currency, image_url |
kindrequired | string | Smart column kind: ai, http, formula, integration, or lookup |
configrequired | object | Kind-specific configuration. See each kind section below for required fields. |
rate_limit | string | object | Preset name ("aggressive", "moderate", "conservative", "gentle") or custom object with requests_per_second, max_concurrent, retry_strategy, max_retries, retry_delay_ms, cool_down_on_429. |
auto_run | booleandefault: false | Automatically process new rows when inserted. |
| Preset | Req/s | Concurrent |
|---|---|---|
aggressive | 500 | 6 |
moderate | 50 | 6 |
conservative | 10 | 5 |
gentle | 2 | 1 |
{
"tool": "hypertab_add_smart_column",
"arguments": {
"table": "leads",
"name": "industry",
"type": "text",
"kind": "ai",
"config": {
"prompt": "Classify {{company}} by industry. One word."
},
"rate_limit": "moderate",
"auto_run": true
}
}HTTP Column -- Gemini API Example
Call the Gemini API per row to find the capital of each country. The prompt uses {{country}} to inject the row value.
- url -- Gemini API endpoint with your API key as a query parameter
- method -- POST for Gemini's generateContent endpoint
- headers -- Content-Type must be application/json
- body -- The request payload with
{{country}}template variable injected into the prompt text - extract -- JSONPath-like expression to pull the generated text from Gemini's nested response structure
- run_condition -- Only process rows where the country column is not empty, skipping incomplete data
candidates[0].content.parts[0].text{
"tool": "hypertab_add_smart_column",
"arguments": {
"table": "countries",
"name": "capital",
"type": "text",
"kind": "http",
"config": {
"url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=YOUR_KEY",
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
"body": {
"contents": [{
"parts": [{
"text": "What is the capital of {{country}}? Reply with ONLY the city name."
}]
}],
"generationConfig": {
"temperature": 0
}
},
"extract": "candidates[0].content.parts[0].text",
"run_condition": "{{country}} IS NOT EMPTY"
},
"rate_limit": "conservative"
}
}HTTP Column -- OpenAI API Example
Call the OpenAI API per row to summarize a company. Uses {{company}} and {{website}} template variables.
- url -- OpenAI Chat Completions endpoint
- method -- POST
- headers -- Authorization with Bearer token and Content-Type
- body -- Standard OpenAI chat format with model, messages array, and max_tokens. The user message content uses template variables.
- extract -- Path to the generated text in OpenAI's response:
choices[0].message.content
{
"tool": "hypertab_add_smart_column",
"arguments": {
"table": "leads",
"name": "summary",
"type": "text",
"kind": "http",
"config": {
"url": "https://api.openai.com/v1/chat/completions",
"method": "POST",
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer sk-YOUR_OPENAI_KEY"
},
"body": {
"model": "gpt-4o-mini",
"messages": [
{
"role": "user",
"content": "Summarize {{company}} ({{website}}) in one sentence."
}
],
"max_tokens": 100
},
"extract": "choices[0].message.content"
},
"rate_limit": "moderate"
}
}AI Column (Built-in)
AI columns use hypertab's built-in AI processing. No external API key needed -- just write a prompt with template variables and choose a model. The result is written back to the cell.
| Config Key | Type | Required | Description |
|---|---|---|---|
prompt | string | Yes | The AI prompt. Use {{column}} to inject row values. |
model | string | No | Model identifier (e.g. "claude-haiku-4-20250414"). Defaults to platform default. |
max_tokens | number | No | Maximum tokens in the response. Default: 256. |
temperature | number | No | Sampling temperature (0-1). Lower = more deterministic. Default: 0. |
The prompt supports all template variable syntax. The AI processes each row independently, replacing variables with the row's actual values before sending to the model.
{
"tool": "hypertab_add_smart_column",
"arguments": {
"table": "support_tickets",
"name": "sentiment",
"type": "text",
"kind": "ai",
"config": {
"prompt": "Classify the sentiment of this support ticket:\n\n{{message}}\n\nReply with exactly one word: positive, negative, or neutral",
"model": "claude-haiku-4-20250414",
"max_tokens": 10,
"temperature": 0
},
"rate_limit": "moderate",
"auto_run": true
}
}Formula Column
Formula columns compute a value from other columns in the same row. No external API calls, no rate limiting. The expression is evaluated locally for each row.
| Function / Operator | Description | Example |
|---|---|---|
+, -, *, / | Arithmetic operators | price * quantity |
CONCAT(a, b, ...) | Concatenate strings | CONCAT(first_name, " ", last_name) |
UPPER(text) | Convert to uppercase | UPPER(country) |
LOWER(text) | Convert to lowercase | LOWER(email) |
TRIM(text) | Remove leading/trailing whitespace | TRIM(name) |
LEFT(text, n) | First n characters | LEFT(phone, 3) |
RIGHT(text, n) | Last n characters | RIGHT(zip_code, 4) |
LEN(text) | Character count | LEN(description) |
IF(cond, then, else) | Conditional expression | IF(score > 80, "hot", "cold") |
ROUND(num, decimals) | Round to n decimal places | ROUND(price * 1.1, 2) |
NOW() | Current ISO 8601 timestamp | NOW() |
Expressions reference column names directly (no {{...}} syntax needed). Column names are resolved against the table schema at evaluation time.
{
"tool": "hypertab_add_smart_column",
"arguments": {
"table": "orders",
"name": "total",
"type": "number",
"kind": "formula",
"config": {
"expression": "price * quantity"
}
}
}Integration Column
Integration columns push row data to external services. Each row triggers an outbound request to the configured target. Useful for syncing data to Slack, webhooks, CRMs, or any HTTP endpoint.
| Config Key | Type | Required | Description |
|---|---|---|---|
target | string | Yes | Integration target: "webhook", "slack" |
url | string | Yes | Destination URL to POST data to |
method | string | No | HTTP method. Default: "POST" |
headers | object | No | Custom headers (e.g. Authorization) |
body | object | string | No | Body template with {{column}} variables. If omitted, sends full row as JSON. |
Integration columns write the response status back to the cell (e.g. "200 OK" or "error: timeout"). The body template supports all template variable syntax.
{
"tool": "hypertab_add_smart_column",
"arguments": {
"table": "alerts",
"name": "slack_notify",
"type": "text",
"kind": "integration",
"config": {
"target": "slack",
"url": "https://hooks.slack.com/services/T00/B00/xxx",
"method": "POST",
"body": {
"text": "New alert: {{title}} (severity: {{severity}})"
}
},
"rate_limit": "conservative",
"auto_run": true
}
}Lookup Column
Lookup columns perform a cross-table VLOOKUP. For each row, they find a matching row in another table and return a value from it. No external API calls, no rate limiting.
| Config Key | Type | Required | Description |
|---|---|---|---|
source_table | string | Yes | The table to look up data from |
match_column | string | Yes | Column in the source table to match against the current row value |
return_column | string | Yes | Column in the source table whose value to return |
The lookup matches the current row's column value (same name as match_column) against the source table. If a match is found, the value from return_column is written to the cell. If no match is found, the cell is left empty.
customer_id column and you want to pull company_name from the customers table.{
"tool": "hypertab_add_smart_column",
"arguments": {
"table": "orders",
"name": "customer_company",
"type": "text",
"kind": "lookup",
"config": {
"source_table": "customers",
"match_column": "customer_id",
"return_column": "company_name"
}
}
}Run Conditions
Run conditions let you skip rows that don't have the required data. Add a run_condition to any smart column's config. Rows that don't match the condition are marked as "skipped" instead of "error".
| Operator | Syntax | Description |
|---|---|---|
IS EMPTY | {{col}} IS EMPTY | True if the column value is null or empty string |
IS NOT EMPTY | {{col}} IS NOT EMPTY | True if the column has a value |
EQUALS | {{col}} EQUALS "value" | True if the column equals the given string |
NOT EQUALS | {{col}} NOT EQUALS "value" | True if the column does not equal the string |
CONTAINS | {{col}} CONTAINS "text" | True if the column contains the substring |
GREATER THAN | {{col}} GREATER THAN 100 | True if the numeric value exceeds the threshold |
LESS THAN | {{col}} LESS THAN 50 | True if the numeric value is below the threshold |
AND | expr AND expr | Both conditions must be true |
OR | expr OR expr | At least one condition must be true |
| Condition | Meaning |
|---|---|
{{website}} IS NOT EMPTY | Only process rows that have a website |
{{size}} GREATER THAN 100 | Only companies with 100+ employees |
{{status}} EQUALS "active" | Only active rows |
{{email}} IS NOT EMPTY AND {{company}} IS NOT EMPTY | Rows with both email and company |
{{score}} GREATER THAN 50 OR {{priority}} EQUALS "high" | High-scoring or high-priority rows |
{{company_data.industry}} IS NOT EMPTY AND {{size}} GREATER THAN 50 | JSON field access with numeric comparison |
hypertab_update_column_config
/api/tables/:tableId/columns/:col/confighypertab_update_column_configUpdate the configuration of a smart column after creation. Change the AI prompt, HTTP URL, formula expression, rate limit preset, or auto-run setting. Only provided fields are updated; omitted fields are left unchanged.
| Parameter | Type | Description |
|---|---|---|
tablerequired | string | Table name or ID |
columnrequired | string | Smart column name or ID |
config | object | Updated kind-specific config (merged with existing config). Only include fields you want to change. |
rate_limit | string | object | Updated rate limit preset or custom config |
auto_run | boolean | Updated auto-run setting |
Config updates are merged with the existing config. For example, updating just the prompt on an AI column preserves the model and temperature settings.
hypertab_run_column to trigger reprocessing after a config change.{
"tool": "hypertab_update_column_config",
"arguments": {
"table": "leads",
"column": "sentiment",
"config": {
"prompt": "Classify sentiment as: very_positive, positive, neutral, negative, very_negative\n\n{{message}}"
}
}
}hypertab_run_column
/api/tables/:tableId/columns/:col/runhypertab_run_columnTrigger smart column processing for all rows or specific rows. Creates a column run and enqueues cells for batch processing. Rate limits are enforced per column config.
| Parameter | Type | Description |
|---|---|---|
tablerequired | string | Table name or ID |
columnrequired | string | Smart column name or ID |
row_ids | string[] | Specific row IDs to process. Omit to process all rows. |
When triggered, the engine creates a column run record, evaluates run conditions for each row, and enqueues matching cells for batch processing. Progress can be tracked using the returned run_id.
{
"tool": "hypertab_run_column",
"arguments": {
"table": "countries",
"column": "capital"
}
}hypertab_get_column_run_status
/api/column-runs/:runIdhypertab_get_column_run_statusCheck the progress of a smart column run. Shows total rows, processed count, error count, and completion status. Use the run_id returned by hypertab_run_column.
| Parameter | Type | Description |
|---|---|---|
run_idrequired | string | Column run ID returned by hypertab_run_column |
Poll this endpoint to track progress. The run transitions through states:
running-- cells are being processedcomplete-- all cells finished (some may have errors)failed-- circuit breaker tripped, run halted
{
"tool": "hypertab_get_column_run_status",
"arguments": {
"run_id": "run_abc123"
}
}hypertab_get_cell_states
/api/tables/:tableId/columns/:col/cellshypertab_get_cell_statesGet per-cell execution states for a smart column. Each cell in a smart column has its own execution state tracking. Filter by status to find failures or pending cells.
| Parameter | Type | Description |
|---|---|---|
tablerequired | string | Table name or ID |
columnrequired | string | Smart column name or ID |
status | string | Filter by cell status: idle, pending, running, complete, error, skipped |
limit | numberdefault: 100 | Max cells to return. |
offset | numberdefault: 0 | Number of cells to skip for pagination. |
| Status | Meaning |
|---|---|
idle | Not yet queued for processing |
pending | Queued and waiting to be processed |
running | Currently being processed |
complete | Successfully processed |
error | Processing failed (see error message) |
skipped | Run condition not met for this row |
{
"tool": "hypertab_get_cell_states",
"arguments": {
"table": "countries",
"column": "capital",
"status": "error"
}
}hypertab_retry_failed_cells
/api/tables/:tableId/columns/:col/retryhypertab_retry_failed_cellsRetry all failed cells in a smart column. Creates a new column run for just the cells with "error" status, re-enqueuing them for processing.
| Parameter | Type | Description |
|---|---|---|
tablerequired | string | Table name or ID |
columnrequired | string | Smart column name or ID |
Only cells in "error" state are retried. Cells that completed successfully or were skipped are not affected. The retry creates a new run_id that you can track with hypertab_get_column_run_status.
hypertab_get_cell_states with status: "error" to understand why cells failed. If the issue is a bad config (wrong URL, invalid API key), fix it with hypertab_update_column_config before retrying.{
"tool": "hypertab_retry_failed_cells",
"arguments": {
"table": "countries",
"column": "capital"
}
}Cell Details (Structured JSON Response)
Every AI and HTTP smart column stores a structured JSON response with metadata alongside the extracted value. Click any completed cell in the UI to open the Cell Details Panel showing all response fields with the ability to add any field as a new column.
/api/tables/:tableId/rows/:rowId/cells/:columnNameGet the full response metadata for a specific cell.
| Parameter | Type | Description |
|---|---|---|
tableIdrequired | string | Table name or ID |
rowIdrequired | string | Row _ht_id |
columnNamerequired | string | Smart column name |
curl /api/tables/countries/rows/ROW_ID/cells/capital \
-H "Authorization: Bearer ht_sk_..."result or output (for structured JSON), model, provider, input_tokens, output_tokens, time_taken_seconds, cost_usd. HTTP columns include: result or output (for multi-extract), http_status, time_taken_seconds, attempts.Structured JSON Output (Clay Model)
AI columns can return structured JSON instead of plain text. Define an output_schema in the column config, and the AI will return a JSON object matching that schema. The cell shows the first field value with aJSON badge. Click the cell to expand all fields.
{
"tool": "hypertab_add_smart_column",
"arguments": {
"table": "my_leads",
"name": "research",
"type": "json",
"kind": "ai",
"config": {
"provider_id": "prv_...",
"model": "gemini-2.5-flash",
"prompt": "Research {{company}} ({{website}}).",
"output_schema": {
"type": "object",
"properties": {
"industry": { "type": "string" },
"employee_count": { "type": "number" },
"hq_city": { "type": "string" },
"revenue": { "type": "string" }
},
"required": ["industry", "employee_count", "hq_city", "revenue"]
},
"run_condition": "{{company}} IS NOT EMPTY"
}
}
}HTTP Column, Advanced Features
HTTP columns support Clay-level configuration: query parameters, retries, timeouts, multi-extract, saved API accounts, and more.
| Parameter | Type | Description |
|---|---|---|
query_params | object | Key-value pairs appended as ?k=v. Supports {{variables}}. |
extracts | object | Multiple named extractions: {"email": "data.email", "name": "data.name"}. Creates structured JSON. |
timeout_ms | number | Response timeout in ms (default 30000, max 120000). |
retry_on_failure | boolean | Auto-retry failed requests. |
max_retries | number | Number of retry attempts (default 3). |
retry_status_codes | array | Which HTTP codes trigger retry (default: [429, 500, 502, 503, 504]). |
retry_delay_ms | number | Delay between retries in ms (default 1000). Linear backoff. |
remove_empty_values | boolean | Strip null/empty fields from request body. |
return_metadata | boolean | Include response headers and redirect info in cell details. |
follow_redirects | boolean | Follow HTTP redirects (default true). |
account_id | string | Saved API account ID, auto-injects auth headers. See hypertab_list_api_accounts. |
{
"config": {
"url": "https://api.github.com/orgs/{{company}}",
"method": "GET",
"account_id": "acct_...",
"extracts": {
"repos": "public_repos",
"followers": "followers",
"blog": "blog",
"location": "location"
},
"timeout_ms": 10000,
"retry_on_failure": true,
"max_retries": 2,
"retry_status_codes": [429, 500, 502, 503]
}
}API Accounts (Saved Auth Headers)
Save named API accounts with auth headers. Use account_id in HTTP column config to auto-inject headers without pasting API keys every time.
{
"tool": "hypertab_save_api_account",
"arguments": {
"name": "My GitHub API",
"service": "github",
"auth_type": "bearer",
"token": "ghp_your_token_here",
"base_url": "https://api.github.com",
"description": "GitHub production API key"
}
}Authorization: Bearer <token>api_key,
X-API-Key: <token> (custom header name supported)basic,
Authorization: Basic base64(user:pass)custom_headers, Any JSON headers object
Manage accounts: hypertab_list_api_accounts, hypertab_update_api_account, hypertab_delete_api_account. Or use Settings → API Accounts in the UI.
Pipeline Tabs (Connected Stages)
A table can contain multiple tabs (pipeline stages). Each tab has its own columns and rows. Linked tabs auto-sync data from a parent tab based on filter conditions. JSON fields from smart columns are expanded into real columns on the linked tab.
{
"tool": "hypertab_create_tab",
"arguments": {
"table": "my_leads",
"name": "qualified_leads",
"source_column": "research",
"filter": {
"research.employee_count": { "gte": 500 }
},
"description": "Leads with 500+ employees"
}
}
// Creates a new tab that:
// 1. Inherits parent columns (company, website)
// 2. Expands JSON fields from 'research' column (industry, employee_count, hq_city, revenue)
// 3. Only syncs rows where employee_count >= 500Each tab is a stage. Data flows forward, gets richer at each stage. Like Clay's pipeline model.
Auto-Run on New Rows
Set auto_run: true in a smart column's config to automatically process new rows when they're inserted. The column run triggers immediately afterhypertab_insert_rows completes.
{
"tool": "hypertab_update_column_config",
"arguments": {
"table": "my_leads",
"column": "research",
"config": { "auto_run": true }
}
}
// Now when you insert rows:
// hypertab_insert_rows({ table: "my_leads", rows: [...] })
// → 'research' column automatically starts processing the new rows