> ## Documentation Index
> Fetch the complete documentation index at: https://darkbanner.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Table

> Read, write, and query data in Zygo's built-in data tables

The **Table** node interacts with Zygo's built-in data tables — a simple, schema-optional key-value store scoped to your tenant. Use it to persist data between flow runs, store records, look up values, or maintain state.

## When to Use It

* Saving form submissions or API responses for later reference
* Looking up records to enrich data in your flow
* Maintaining a running log of events or transactions
* Building a simple database for your workflows without an external service
* Tracking state across multiple flow executions (e.g., "last synced at")

## Operations

The Table node supports several operations depending on what you need:

> [tab] Insert
>
> Add a new record to a table.
>
> **Configuration:**
>
> | Field | Description |
> | - | - |
> | **Table Name** | The table to insert into. Created automatically if it doesn't exist. |
> | **Record Key** | Optional. A string key for looking up this record later. |
> | **Data** | The data to store, as a JSON object. Supports template syntax. |
>
> **Example data:**
>
> ```json theme={null}
> {
>   "name": "{{1_Form.form_data.name}}",
>   "email": "{{1_Form.form_data.email}}",
>   "submitted_at": "{{1_Form.form_data.timestamp}}",
>   "source": "contact_form"
> }
> ```

> [tab] Update
>
> Update an existing record by its ID or key.
>
> **Configuration:**
>
> | Field | Description |
> | - | - |
> | **Table Name** | The table containing the record |
> | **Record ID or Key** | Identify which record to update |
> | **Data** | The new data (replaces existing data) |

> [tab] Query
>
> Look up records from a table.
>
> **Configuration:**
>
> | Field | Description |
> | - | - |
> | **Table Name** | The table to query |
> | **Record Key** | Optional. Filter by a specific key |
> | **Limit** | Maximum number of records to return |
>
> Returns the matching records as an array.

> [tab] Delete
>
> Remove a record from a table by ID.
>
> **Configuration:**
>
> | Field | Description |
> | - | - |
> | **Table Name** | The table containing the record |
> | **Record ID** | The ID of the record to delete |

## Table Schemas

Tables in Zygo are schema-optional. You can insert any JSON object without defining columns first. However, defining a schema gives you:

* A structured view in the data tables UI
* Column names and types visible when browsing records
* Validation when editing records manually

To manage schemas, go to **Data Tables** in the sidebar and click on a table's schema settings.

## Output

The Table node's output varies by operation:

| Operation | Output |
| - | - |
| **Insert** | `{ "success": true, "action": "insert", "table": "...", "id": "...", "key": "...", "data": {...} }` |
| **Update** | `{ "ok": true, "record": {...} }` |
| **Query** | `{ "table": "...", "total": 5, "records": [...] }` |
| **Delete** | `{ "ok": true }` |

Reference these in downstream nodes:

```
New record ID: {{2_Table.id}}
First queried name: {{2_Table.records[0].data.name}}
Total matches: {{2_Table.total}}
```

## Common Patterns

> [accordion] Log every form submission
>
> Connect a Table node after a Web Form to persist every submission:
>
> * **Operation:** Insert
> * **Table Name:** `form_submissions`
> * **Record Key:** `{{1_Form.form_data.email}}`
> * **Data:** `{{1_Form.form_data}}`
>
> This creates a searchable log of all submissions, keyed by email for easy lookup.

> [accordion] Deduplication check
>
> Before processing a webhook payload, check if you've already seen this event:
>
> 1. **Table node (Query)** — Look up by record key (e.g., the event's unique ID)
> 2. **Condition node** — Check if `records` is empty
> 3. **True (new)** → Process the event, then insert a record
> 4. **False (duplicate)** → Skip

> [accordion] Store and retrieve configuration
>
> Use a table as a simple config store:
>
> * **Table:** `config`
> * **Key:** `email_settings`
> * **Data:** `{ "from": "noreply@acme.com", "footer": "..." }`
>
> A downstream Request node can reference:
>
> ```
> {{2_Table.records[0].data.from}}
> ```

> [accordion] Running counter or state
>
> Track cumulative state across flow runs:
>
> 1. **Query** the current counter record by key
> 2. **Python node** — Increment the value
> 3. **Update** the record with the new value
>
> Useful for things like "total submissions this month" or "last processed order ID."

> [!NOTE]
>
> Data tables are scoped to your tenant. Different tenants have completely separate tables, even if the table names are the same.

> [!TIP]
>
> Use descriptive table names and record keys. A table called `customer_signups` with keys like `jane@acme.com` is much easier to debug than `data1` with auto-generated keys.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.