Tables API
Tables provide structured data storage for agents and users. Each table has typed columns, queryable rows with filtering and sorting, import/export support, automation triggers, chart visualizations, and full change history with rollback.
Quick Start
Create a table, add columns, insert rows, and query with filters — a typical integration flow:
// 1. Create a table with initial columns
const table: { id: string; name: string } = await fetch('/api/tables', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: 'Customer Feedback',
projectId: 'proj-8f3a-4b2c',
columns: [
{ name: 'customer', displayName: 'Customer', dataType: 'text', position: 0 },
{ name: 'rating', displayName: 'Rating', dataType: 'number', position: 1 },
{ name: 'feedback', displayName: 'Feedback', dataType: 'text', position: 2 },
],
}),
}).then((r) => r.json());
// → { id: "tbl-6c1d-9e7f", name: "Customer Feedback", ... }
// 2. Add a status column after creation
await fetch(`/api/tables/${table.id}/columns`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: 'status',
displayName: 'Status',
dataType: 'select',
config: { options: ['open', 'in_progress', 'closed'] },
}),
});
// 3. Insert rows in batch (up to 1000 per request)
await fetch(`/api/tables/${table.id}/rows`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
rows: [
{ data: { customer: 'Acme Corp', rating: 5, feedback: 'Excellent', status: 'closed' } },
{ data: { customer: 'Globex Inc', rating: 3, feedback: 'Average', status: 'open' } },
{ data: { customer: 'Initech', rating: 4, feedback: 'Good support', status: 'closed' } },
],
}),
});
// 4. Query with filters — find high-rated feedback
const filters: string = JSON.stringify([{ column: 'rating', operator: 'gte', value: 4 }]);
const rows: Array<{ data: Record<string, unknown> }> = await fetch(
`/api/tables/${table.id}/rows?filters=${encodeURIComponent(filters)}`
).then((r) => r.json());
console.log(`${rows.length} rows with rating >= 4`); Base URL
/api/tables
Endpoints
List Tables
/api/tables Retrieve all tables with optional filtering by project, source, or search term.
Query Parameters
| Param | Type | Req | Description |
|---|---|---|---|
| projectId | string | — | Filter by project ID |
| source | enum | — | manual, imported, agent, or template |
| search | string | — | Search by table name |
List all tables for a project — useful for building a data browser or selecting a table to query:
// List all tables in a project
const response: Response = await fetch('/api/tables?projectId=proj-8f3a-4b2c');
const tables: Array<{ id: string; name: string; source: string }> = await response.json();
tables.forEach((t) => console.log(`${t.name} (${t.source}) — ${t.id}`)); Example response:
[
{
"id": "tbl-6c1d-9e7f",
"name": "Customer Feedback",
"description": null,
"projectId": "proj-8f3a-4b2c",
"source": "manual",
"rowCount": 42,
"createdAt": "2026-04-03T10:00:00.000Z",
"updatedAt": "2026-04-03T11:30:00.000Z"
}
] Create Table
/api/tables Create a new table with optional column definitions. If a templateId is provided, the table is cloned from that template instead.
Request Body
| Field | Type | Req | Description |
|---|---|---|---|
| name | string | * | Table name (1-256 characters) |
| description | string | — | Table description (max 1024 characters) |
| projectId | string (UUID) | — | Link to a project |
| columns | ColumnDef[] | — | Initial column definitions (see Column Schema below) |
| source | enum | — | manual, imported, agent, or template |
| templateId | string (UUID) | — | Clone from an existing template |
Response 201 Created — New table object
Errors: 400 — Zod validation failure
Create a table with typed columns — columns define the schema that rows must follow:
// Create a table with typed columns
const response: Response = await fetch('/api/tables', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: 'Customer Feedback',
projectId: 'proj-8f3a-4b2c',
columns: [
{ name: 'customer', displayName: 'Customer', dataType: 'text', position: 0 },
{ name: 'rating', displayName: 'Rating', dataType: 'number', position: 1 },
{ name: 'feedback', displayName: 'Feedback', dataType: 'text', position: 2 },
],
}),
});
const table: { id: string } = await response.json();
console.log(table.id); // "tbl-6c1d-9e7f" Example response:
{
"id": "tbl-6c1d-9e7f",
"name": "Customer Feedback",
"projectId": "proj-8f3a-4b2c",
"source": "manual",
"columns": [
{ "id": "col-a1b2", "name": "customer", "displayName": "Customer", "dataType": "text", "position": 0 },
{ "id": "col-c3d4", "name": "rating", "displayName": "Rating", "dataType": "number", "position": 1 },
{ "id": "col-e5f6", "name": "feedback", "displayName": "Feedback", "dataType": "text", "position": 2 }
],
"createdAt": "2026-04-03T10:00:00.000Z"
} Clone from Template
/api/tables Create a table by cloning a template. Provide templateId in the request body to use this path.
Request Body
| Field | Type | Req | Description |
|---|---|---|---|
| templateId | string (UUID) | * | Template to clone |
| name | string | * | Name for the new table (1-256 characters) |
| projectId | string (UUID) | — | Link to a project |
| includeSampleData | boolean | — | Include sample rows from the template |
Clone a template to get a pre-configured table with columns and optional sample data:
// Clone a template with sample data included
const response: Response = await fetch('/api/tables', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
templateId: 'tpl-4a2b-8c9d',
name: 'Q3 Budget Tracker',
projectId: 'proj-8f3a-4b2c',
includeSampleData: true,
}),
});
const table: { id: string; name: string } = await response.json(); Get Table
/api/tables/{id} Retrieve a single table by ID including its column definitions.
Response 200 — Table object with columns array
// Fetch table metadata and column definitions
const table: { name: string; columns: Array<{ displayName: string; dataType: string }> } =
await fetch('/api/tables/tbl-6c1d-9e7f').then((r) => r.json());
console.log(`${table.name} — ${table.columns.length} columns`);
table.columns.forEach((c) => console.log(` ${c.displayName} (${c.dataType})`)); Errors: 404 — { "error": "Table not found" }
Update Table
/api/tables/{id} Update table name, description, or project association.
Request Body (all fields optional)
| Field | Type | Req | Description |
|---|---|---|---|
| name | string | — | Updated name (1-256 chars) |
| description | string | — | Updated description (max 1024 chars) |
| projectId | string (UUID) | null | — | Reassign or unlink project |
Response 200 — Updated table object
Errors: 400 — Validation failure, 404 — Not found
// Update table name
await fetch('/api/tables/tbl-6c1d-9e7f', {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Customer Feedback v2' }),
}); Delete Table
/api/tables/{id} Permanently delete a table and all its rows, columns, triggers, charts, and history.
Response 204 No Content
Errors: 404 — Not found
// Delete a table and all associated data
await fetch('/api/tables/tbl-6c1d-9e7f', { method: 'DELETE' }); Rows
List Rows
/api/tables/{id}/rows Query rows with filtering, sorting, and pagination. Filters and sorts are passed as JSON-encoded query parameters.
Query Parameters
| Param | Type | Req | Description |
|---|---|---|---|
| limit | number | — | Max rows to return (1-1000) |
| offset | number | — | Number of rows to skip |
| filters | JSON string | — | Array of FilterSpec objects (see Filtering below) |
| sorts | JSON string | — | Array of SortSpec objects (see Sorting below) |
Query rows with filters and pagination — useful for building data views or feeding data to agents:
// Query with filters and sorting
const filters: string = JSON.stringify([
{ column: 'rating', operator: 'gte', value: 4 },
{ column: 'status', operator: 'eq', value: 'open' },
]);
const sorts: string = JSON.stringify([
{ column: 'rating', direction: 'desc' },
]);
const rows: Array<{ data: { customer: string; rating: number; feedback: string } }> = await fetch(
`/api/tables/tbl-6c1d-9e7f/rows?limit=50&filters=${encodeURIComponent(filters)}&sorts=${encodeURIComponent(sorts)}`
).then((r) => r.json());
rows.forEach((row) => {
console.log(`${row.data.customer}: ${row.data.rating}/5 — ${row.data.feedback}`);
}); Example response:
[
{
"id": "row-a1b2-c3d4",
"tableId": "tbl-6c1d-9e7f",
"data": {
"customer": "Acme Corp",
"rating": 5,
"feedback": "Excellent support and fast resolution",
"status": "open"
},
"createdBy": "claude-code",
"createdAt": "2026-04-03T10:30:00.000Z",
"updatedAt": "2026-04-03T10:30:00.000Z"
}
] Add Rows
/api/tables/{id}/rows Insert one or more rows into a table. Accepts a batch of up to 1000 rows per request.
Request Body
| Field | Type | Req | Description |
|---|---|---|---|
| rows | Array | * | Array of row objects (1-1000 items) |
| rows[].data | Record<string, unknown> | * | Column name to value mapping |
| rows[].createdBy | string | — | Creator identifier (e.g. agent name) |
Response 201 Created — Array of created rows
Insert a batch of rows — agents often use this to populate tables with structured results:
// Batch insert rows (up to 1000 per request)
const result: Array<{ id: string }> = await fetch('/api/tables/tbl-6c1d-9e7f/rows', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
rows: [
{ data: { customer: 'Acme Corp', rating: 5, feedback: 'Excellent' }, createdBy: 'claude-code' },
{ data: { customer: 'Globex Inc', rating: 3, feedback: 'Average' }, createdBy: 'claude-code' },
],
}),
}).then((r) => r.json());
console.log(`Inserted ${result.length} rows`); Errors: 400 — Validation failure, 404 — Table not found
Update Row
/api/tables/{id}/rows/{rowId} Update the data for a single row. The entire data object is replaced.
Request Body
| Field | Type | Req | Description |
|---|---|---|---|
| data | Record<string, unknown> | * | Updated column name to value mapping |
Response 200 — Updated row
Replace a row’s data — note that the entire data object is replaced, not merged:
// Update a row — full data replacement
await fetch('/api/tables/tbl-6c1d-9e7f/rows/row-a1b2-c3d4', {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
data: { customer: 'Acme Corp', rating: 4, feedback: 'Good, improved response time', status: 'closed' },
}),
}); Errors: 400 — Validation failure, 404 — Row not found
Delete Row
/api/tables/{id}/rows/{rowId} Permanently delete a single row.
Response 204 No Content
// Delete a single row
await fetch('/api/tables/tbl-6c1d-9e7f/rows/row-a1b2-c3d4', { method: 'DELETE' }); Columns
Add Column
/api/tables/{id}/columns Add a new column to an existing table.
Request Body
| Field | Type | Req | Description |
|---|---|---|---|
| name | string | * | Column key (1-64 chars, unique per table) |
| displayName | string | * | Display label (1-128 chars) |
| dataType | enum | * | text, number, boolean, date, select, url, email, computed, or relation |
| required | boolean | — | Whether the column is required |
| defaultValue | string | null | — | Default value for new rows |
| config | ColumnConfig | — | Type-specific config (see Column Config below) |
Response 201 Created — New column object
Add a select column with predefined options — great for status tracking:
// Add a select column with options
const column: { id: string; name: string } = await fetch('/api/tables/tbl-6c1d-9e7f/columns', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: 'status',
displayName: 'Status',
dataType: 'select',
config: { options: ['open', 'in_progress', 'closed'] },
}),
}).then((r) => r.json()); Example response:
{
"id": "col-g7h8",
"tableId": "tbl-6c1d-9e7f",
"name": "status",
"displayName": "Status",
"dataType": "select",
"position": 3,
"config": { "options": ["open", "in_progress", "closed"] },
"createdAt": "2026-04-03T10:05:00.000Z"
} Reorder Columns
/api/tables/{id}/columns Reorder all columns by providing column IDs in the desired order.
Request Body
| Field | Type | Req | Description |
|---|---|---|---|
| columnIds | string[] | * | Column IDs in the desired display order |
Response 200 — Reordered columns array
// Move status column to the front
await fetch('/api/tables/tbl-6c1d-9e7f/columns', {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
columnIds: ['col-g7h8', 'col-a1b2', 'col-c3d4', 'col-e5f6'],
}),
}); Import & Export
Import Data
/api/tables/{id}/import Import structured data from a document into the table. Supports a preview mode to inspect inferred columns and sample rows before committing. Column types are auto-inferred from the first 100 rows.
Request Body
| Field | Type | Req | Description |
|---|---|---|---|
| documentId | string (UUID) | * | Source document to import from |
| preview | boolean | — | Set true to preview without importing |
| columnMapping | Array | — | Override inferred column names, types, or skip columns |
| columnMapping[].name | string | * | Column key |
| columnMapping[].displayName | string | * | Display label |
| columnMapping[].dataType | string | * | Column data type |
| columnMapping[].skip | boolean | — | Set true to skip this column |
Preview Response
| Field | Type | Req | Description |
|---|---|---|---|
| headers | string[] | * | Detected column headers |
| sampleRows | Array | * | First 10 rows of data |
| totalRows | number | * | Total row count in source |
| inferredColumns | ColumnDef[] | * | Auto-inferred column definitions |
Import Response
| Field | Type | Req | Description |
|---|---|---|---|
| importId | string | * | Audit record ID |
| rowsImported | number | * | Successfully imported rows |
| rowsSkipped | number | * | Skipped rows (validation errors) |
| errors | Array | * | First 20 error details |
| columns | ColumnDef[] | * | Final column definitions used |
Preview an import before committing — inspect inferred column types and sample data, then execute:
// Preview first, then import
const preview: { totalRows: number; headers: string[] } = await fetch(
'/api/tables/tbl-6c1d-9e7f/import',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ documentId: 'doc-7b2e-3f9a', preview: true }),
}
).then((r) => r.json());
console.log(`${preview.totalRows} rows, ${preview.headers.length} columns detected`);
// Execute the import
const result: { rowsImported: number; rowsSkipped: number } = await fetch(
'/api/tables/tbl-6c1d-9e7f/import',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ documentId: 'doc-7b2e-3f9a' }),
}
).then((r) => r.json());
console.log(`Imported ${result.rowsImported}, skipped ${result.rowsSkipped}`); Example preview response:
{
"headers": ["customer", "rating", "feedback"],
"sampleRows": [
{ "customer": "Acme Corp", "rating": "5", "feedback": "Excellent" }
],
"totalRows": 150,
"inferredColumns": [
{ "name": "customer", "displayName": "customer", "dataType": "text" },
{ "name": "rating", "displayName": "rating", "dataType": "number" },
{ "name": "feedback", "displayName": "feedback", "dataType": "text" }
]
} Export Table
/api/tables/{id}/export Download the entire table as CSV, JSON, or XLSX. Returns up to 10,000 rows.
Query Parameters
| Param | Type | Req | Description |
|---|---|---|---|
| format | enum | — | csv (default), json, or xlsx |
Response 200 — File download with appropriate Content-Type and Content-Disposition headers
Export a table for external use — CSV for spreadsheets, JSON for programmatic access, XLSX for stakeholders:
// Download as CSV and trigger browser save
const res: Response = await fetch('/api/tables/tbl-6c1d-9e7f/export?format=csv');
const blob: Blob = await res.blob();
const url: string = URL.createObjectURL(blob);
const link: HTMLAnchorElement = document.createElement('a');
link.href = url;
link.download = 'customer-feedback.csv';
link.click(); Triggers
List Triggers
/api/tables/{id}/triggers List all automation triggers configured for a table.
Response Body (Array)
| Field | Type | Req | Description |
|---|---|---|---|
| id | string (UUID) | * | Trigger identifier |
| tableId | string (UUID) | * | Parent table ID |
| name | string | * | Trigger name |
| triggerEvent | enum | * | row_added, row_updated, or row_deleted |
| condition | JSON | null | — | Optional condition expression |
| actionType | enum | * | run_workflow or create_task |
| actionConfig | JSON | * | Action-specific configuration |
| status | enum | * | active or paused |
| fireCount | number | * | Times this trigger has fired |
List triggers to see what automations are active on a table:
// Check which triggers are active
const triggers: Array<{ name: string; status: string; triggerEvent: string; actionType: string; fireCount: number }> =
await fetch('/api/tables/tbl-6c1d-9e7f/triggers').then((r) => r.json());
triggers.forEach((t) => {
console.log(`${t.name} [${t.status}] — ${t.triggerEvent} → ${t.actionType} (fired ${t.fireCount}x)`);
}); Example response:
[
{
"id": "trg-5e4d-3c2b",
"tableId": "tbl-6c1d-9e7f",
"name": "Auto-triage feedback",
"triggerEvent": "row_added",
"condition": null,
"actionType": "run_workflow",
"actionConfig": { "workflowId": "wf-2a3b-4c5d" },
"status": "active",
"fireCount": 28
}
] Create Trigger
/api/tables/{id}/triggers Create a new automation trigger that fires when rows are added, updated, or deleted.
Request Body
| Field | Type | Req | Description |
|---|---|---|---|
| name | string | * | Trigger name |
| triggerEvent | enum | * | row_added, row_updated, or row_deleted |
| condition | object | — | Condition that must be met for the trigger to fire |
| actionType | enum | * | run_workflow or create_task |
| actionConfig | object | * | Action configuration (e.g. workflowId, task template) |
Response 201 Created — New trigger object
Create a trigger that automatically runs a workflow when new feedback is added:
// Auto-run a triage workflow when new rows are added
const trigger: { id: string; name: string } = await fetch('/api/tables/tbl-6c1d-9e7f/triggers', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: 'Auto-triage feedback',
triggerEvent: 'row_added',
actionType: 'run_workflow',
actionConfig: { workflowId: 'wf-2a3b-4c5d' },
}),
}).then((r) => r.json()); Update Trigger
/api/tables/{id}/triggers/{triggerId} Update a trigger's name, event, condition, action, or status.
Request Body (all fields optional)
| Field | Type | Req | Description |
|---|---|---|---|
| name | string | — | Updated name |
| triggerEvent | enum | — | row_added, row_updated, or row_deleted |
| status | enum | — | active or paused |
| condition | object | null | — | Updated condition (null to remove) |
| actionType | enum | — | run_workflow or create_task |
| actionConfig | object | — | Updated action configuration |
Response 200 — Updated trigger object
Errors: 404 — Trigger not found
Pause a trigger temporarily during maintenance:
// Pause a trigger during maintenance
await fetch('/api/tables/tbl-6c1d-9e7f/triggers/trg-5e4d-3c2b', {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ status: 'paused' }),
}); Delete Trigger
/api/tables/{id}/triggers/{triggerId} Permanently delete a trigger.
Response 204 No Content
Errors: 404 — Trigger not found
// Delete a trigger
await fetch('/api/tables/tbl-6c1d-9e7f/triggers/trg-5e4d-3c2b', { method: 'DELETE' }); Charts
List Charts
/api/tables/{id}/charts List all chart visualizations saved for a table.
Response Body (Array)
| Field | Type | Req | Description |
|---|---|---|---|
| id | string (UUID) | * | Chart view ID |
| name | string | * | Chart title |
| config | object | * | Chart configuration (type, xColumn, yColumn, aggregation) |
| createdAt | ISO 8601 | * | Creation timestamp |
// List all charts for a table
const charts: Array<{ name: string; config: { type: string } }> =
await fetch('/api/tables/tbl-6c1d-9e7f/charts').then((r) => r.json());
charts.forEach((c) => console.log(`${c.name} (${c.config.type})`)); Create Chart
/api/tables/{id}/charts Save a new chart visualization for a table.
Request Body
| Field | Type | Req | Description |
|---|---|---|---|
| type | string | * | Chart type (e.g. bar, line, pie, scatter) |
| title | string | * | Chart display title |
| xColumn | string | * | Column name for X axis |
| yColumn | string | — | Column name for Y axis |
| aggregation | string | — | Aggregation function (e.g. sum, count, avg) |
Response 201 Created — { "id": "...", "name": "..." }
Create a bar chart showing the distribution of customer ratings:
// Create a ratings distribution chart
const chart: { id: string; name: string } = await fetch('/api/tables/tbl-6c1d-9e7f/charts', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
type: 'bar',
title: 'Ratings Distribution',
xColumn: 'rating',
aggregation: 'count',
}),
}).then((r) => r.json()); Update Chart
/api/tables/{id}/charts/{chartId} Update a chart's title, type, axes, or aggregation. Config fields are merged with the existing configuration.
Request Body (all fields optional)
| Field | Type | Req | Description |
|---|---|---|---|
| title | string | — | Updated chart title |
| type | string | — | Updated chart type |
| xColumn | string | — | Updated X axis column |
| yColumn | string | — | Updated Y axis column |
| aggregation | string | — | Updated aggregation function |
Response 200 — Updated chart object with parsed config
Errors: 404 — Chart not found
// Switch to pie chart
await fetch('/api/tables/tbl-6c1d-9e7f/charts/chart-a1b2-c3d4', {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ type: 'pie', title: 'Ratings Breakdown' }),
}); Delete Chart
/api/tables/{id}/charts/{chartId} Permanently delete a chart visualization.
Response 204 No Content
Errors: 404 — Chart not found
// Delete a chart
await fetch('/api/tables/tbl-6c1d-9e7f/charts/chart-a1b2-c3d4', { method: 'DELETE' }); History
Table History
/api/tables/{id}/history Retrieve the change history for a table (row additions, updates, deletions).
Query Parameters
| Param | Type | Req | Description |
|---|---|---|---|
| limit | number | — | Max entries to return (default 100, max 500) |
// Fetch recent change history
const history: Array<{ action: string; rowId: string; createdAt: string }> =
await fetch('/api/tables/tbl-6c1d-9e7f/history?limit=50').then((r) => r.json());
history.forEach((entry) => {
console.log(`[${entry.action}] row ${entry.rowId} at ${entry.createdAt}`);
}); Row History
/api/tables/{id}/rows/{rowId}/history Retrieve the change history for a specific row, showing each version of its data.
Query Parameters
| Param | Type | Req | Description |
|---|---|---|---|
| limit | number | — | Max entries to return (default 50, max 200) |
// View how a row changed over time
const history: Array<{ version: number; data: { rating: number }; createdAt: string }> =
await fetch('/api/tables/tbl-6c1d-9e7f/rows/row-a1b2-c3d4/history').then((r) => r.json());
history.forEach((entry) => {
console.log(`v${entry.version}: rating=${entry.data.rating} at ${entry.createdAt}`);
}); Rollback Row
/api/tables/{id}/rows/{rowId}/history Rollback a row to a previous version by providing a history entry ID.
Request Body
| Field | Type | Req | Description |
|---|---|---|---|
| historyEntryId | string (UUID) | * | History entry to rollback to |
Response 200 — { "ok": true }
Rollback a row to a previous version — useful for undoing accidental edits:
// Rollback a row to a previous version
await fetch('/api/tables/tbl-6c1d-9e7f/rows/row-a1b2-c3d4/history', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ historyEntryId: 'hist-9f8e-7d6c' }),
}); Errors: 400 — Missing historyEntryId, 404 — History entry not found
Templates
List Templates
/api/tables/templates List available table templates, optionally filtered by category or scope.
Query Parameters
| Param | Type | Req | Description |
|---|---|---|---|
| category | enum | — | business, personal, pm, finance, or content |
| scope | enum | — | system or user |
// List project management templates
const { templates }: { templates: Array<{ name: string; scope: string; description: string }> } =
await fetch('/api/tables/templates?category=pm').then((r) => r.json());
templates.forEach((t) => console.log(`${t.name} [${t.scope}] — ${t.description}`)); Save as Template
/api/tables/templates Save an existing table as a reusable user-scoped template. Optionally includes the first 5 rows as sample data.
Request Body
| Field | Type | Req | Description |
|---|---|---|---|
| tableId | string (UUID) | * | Source table to save as template |
| name | string | * | Template name |
| description | string | — | Template description (defaults to table description) |
| category | enum | — | business, personal, pm, finance, or content |
| includeSampleData | boolean | — | Include first 5 rows as sample data |
Response 201 Created — { "id": "...", "name": "..." }
Save a well-designed table as a reusable template for your team:
// Save a table as a reusable template
const template: { id: string } = await fetch('/api/tables/templates', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
tableId: 'tbl-6c1d-9e7f',
name: 'Sprint Planning Board',
category: 'pm',
includeSampleData: true,
}),
}).then((r) => r.json());
console.log(`Template saved: ${template.id}`); Column Config Reference
| Config Field | Applies To | Description |
|---|---|---|
| options | select | Array of allowed option strings |
| formula | computed | Formula expression string |
| formulaType | computed | arithmetic, text_concat, date_diff, conditional, or aggregate |
| resultType | computed | Expected result data type |
| dependencies | computed | Column names the formula depends on |
| targetTableId | relation | ID of the related table |
| displayColumn | relation | Column name to display from the related table |
Filter Operators
| Operator | Description |
|---|---|
| eq | Equal to |
| neq | Not equal to |
| gt / gte | Greater than / greater than or equal |
| lt / lte | Less than / less than or equal |
| contains | String contains |
| starts_with | String starts with |
| in | Value is in array |
| is_empty | Value is null or empty |
| is_not_empty | Value is not null or empty |