Tables

Tables API

Custom data tables allow you to store and manage structured data that agents can query and manipulate.

⚠️
Admin/Owner Only: All table management and data operations require Admin or Owner role.

Table Management

List Tables

GET /orgs/{organizationId}/tables

Query Parameters:

  • limit (optional): Number of results (default: 20)
  • offset (optional): Pagination offset (default: 0)

Response:

{
  "items": [
    {
      "name": "customers",
      "organizationId": "org-123",
      "description": "Customer information",
      "fields": [
        {
          "name": "id",
          "type": "numeric",
          "required": true,
          "comments": "Customer ID"
        },
        {
          "name": "name",
          "type": "text",
          "required": true,
          "comments": "Customer full name"
        },
        {
          "name": "email",
          "type": "text",
          "required": true,
          "comments": "Email address"
        },
        {
          "name": "is_active",
          "type": "boolean",
          "required": false,
          "default": true,
          "comments": "Account status"
        },
        {
          "name": "metadata",
          "type": "jsonb",
          "required": false,
          "comments": "Additional data"
        }
      ],
      "creatorUserId": "user-456",
      "createdAt": "2024-01-01T00:00:00Z",
      "updatedAt": "2024-01-01T00:00:00Z"
    }
  ],
  "totalRows": 1,
  "offset": 0
}

Create Table

POST /orgs/{organizationId}/tables

Required Role: Admin or Owner

Required Fields:

  • name: Table name (must be unique, lowercase, snake_case recommended)
  • fields: Array of field schemas
  • description: Table description

Request Body:

{
  "name": "products",
  "description": "Product catalog",
  "fields": [
    {
      "name": "id",
      "type": "numeric",
      "required": true,
      "comments": "Product ID"
    },
    {
      "name": "name",
      "type": "text",
      "required": true,
      "comments": "Product name"
    },
    {
      "name": "price",
      "type": "numeric",
      "required": false,
      "default": 0,
      "comments": "Price in USD"
    },
    {
      "name": "in_stock",
      "type": "boolean",
      "required": false,
      "default": true,
      "comments": "Availability status"
    },
    {
      "name": "metadata",
      "type": "jsonb",
      "required": false,
      "comments": "Product metadata"
    },
    {
      "name": "created_at",
      "type": "timestamp",
      "required": false,
      "comments": "Creation timestamp"
    }
  ]
}

Field Types:

  • text - Text/string data
  • numeric - Numbers (integers and decimals)
  • boolean - True/false values
  • timestamp - Date and time values
  • jsonb - JSON objects (stored as PostgreSQL JSONB)

Field Schema:

  • name (required): Field name
  • type (required): Field type
  • required (required): Whether field is required (boolean)
  • default (optional): Default value if not provided
  • comments (required): Description/comment for the field

Response: Returns created CustomTable object

Get Table

GET /orgs/{organizationId}/tables/{tableName}

Returns table metadata and field schemas.

Response: Returns CustomTable object

Delete Table

DELETE /orgs/{organizationId}/tables/{tableName}

Required Role: Admin or Owner

Permanently deletes the table and all its data.

Response:

{
  "organizationId": "org-123",
  "tableName": "products"
}
⚠️
There is no update table endpoint. You cannot modify table structure after creation. Create a new table if you need different fields.

Table Data Operations

List Rows

GET /orgs/{organizationId}/tables/{tableName}/data

Query Parameters:

  • limit (optional): Number of rows (default: 20)
  • offset (optional): Pagination offset (default: 0)
  • orderBy (optional): Sort specification (format: field1:asc,field2:desc)
  • filters (optional): Filter specification (format: field:operator:value:join)

Example with Filters and Sorting:

GET /orgs/org-123/tables/products/data?limit=10&offset=0&orderBy=price:desc&filters=in_stock:eq:true:and,price:gte:100

Filter Operators:

  • eq - Equal to
  • ne - Not equal to
  • gt - Greater than
  • lt - Less than
  • gte - Greater than or equal to
  • lte - Less than or equal to
  • ilike - Case-insensitive pattern matching (use % as wildcard)
  • in - In list (comma-separated values)
  • nin - Not in list

Filter Join:

  • and - AND condition with next filter
  • or - OR condition with next filter

Response:

{
  "items": [
    {
      "id": 1,
      "name": "Premium Widget",
      "price": 299.99,
      "in_stock": true,
      "metadata": {
        "category": "electronics",
        "tags": ["featured", "premium"]
      },
      "created_at": "2024-01-01T00:00:00Z"
    }
  ],
  "totalRows": 45,
  "offset": 0
}

Create Row

POST /orgs/{organizationId}/tables/{tableName}/data

Required Role: Admin or Owner

Request Body:

{
  "data": {
    "id": 101,
    "name": "New Product",
    "price": 49.99,
    "in_stock": true,
    "metadata": {
      "category": "accessories"
    }
  }
}

Response: Returns the created row

Update Row

PUT /orgs/{organizationId}/tables/{tableName}/data/{id}

Required Role: Admin or Owner

The {id} parameter is the numeric row ID (auto-generated integer).

Request Body:

{
  "data": {
    "price": 39.99,
    "in_stock": false
  }
}

Only include fields you want to update. Other fields remain unchanged.

Response: Returns the updated row

Delete Row

DELETE /orgs/{organizationId}/tables/{tableName}/data/{id}

Required Role: Admin or Owner

Permanently deletes the row.

Response:

{
  "organizationId": "org-123",
  "tableName": "products",
  "id": 101
}

Bulk Operations

Batch Insert

POST /orgs/{organizationId}/tables/{tableName}/data/batch

Required Role: Admin or Owner

Insert multiple rows in a single request.

Request Body:

{
  "data": [
    {
      "id": 1,
      "name": "Product 1",
      "price": 10.00,
      "in_stock": true
    },
    {
      "id": 2,
      "name": "Product 2",
      "price": 20.00,
      "in_stock": true
    },
    {
      "id": 3,
      "name": "Product 3",
      "price": 30.00,
      "in_stock": false
    }
  ]
}

Response:

{
  "inserted": 3,
  "failed": 0,
  "errors": [],
  "ids": [1, 2, 3]
}

If validation fails for some rows:

{
  "inserted": 2,
  "failed": 1,
  "errors": [
    {
      "index": 1,
      "error": "Invalid record"
    }
  ],
  "ids": [1, 3]
}

Using Tables with Agents

Agents can query and manipulate tables using the database tool.

Example Agent Configuration:

{
  "name": "Inventory Assistant",
  "tools": [
    {
      "toolCode": "database",
      "configuration": {
        "tables": ["products", "inventory"]
      }
    }
  ]
}

The agent can then:

  • “Show me all products under $100”
  • “Update the price of product 123 to $79.99”
  • “Add a new product called ‘Widget Pro’ with price $150”
  • “How many products are currently in stock?”

Filter Examples

Simple Equality

filters=in_stock:eq:true

Multiple Conditions (AND)

filters=in_stock:eq:true:and,price:gte:100

Multiple Conditions (OR)

filters=category:eq:electronics:or,category:eq:accessories

Pattern Matching

filters=name:ilike:%widget%

Matches any product name containing “widget” (case-insensitive)

Numeric Ranges

filters=price:gte:50:and,price:lte:200

Matches prices between $50 and $200

Complex Example

filters=in_stock:eq:true:and,price:gte:100:and,category:in:electronics,accessories

Sorting Examples

Single Field Ascending

orderBy=price:asc

Single Field Descending

orderBy=created_at:desc

Multiple Fields

orderBy=in_stock:desc,price:asc

First by in_stock (descending), then by price (ascending)

Best Practices

  1. Table Naming - Use lowercase snake_case for table names (e.g., customer_orders)
  2. Field Naming - Use lowercase snake_case for field names (e.g., created_at)
  3. Required Fields - Mark critical fields as required
  4. Default Values - Provide sensible defaults when possible
  5. Comments - Always provide descriptive comments for fields
  6. JSONB for Flexibility - Use jsonb type for dynamic/nested data
  7. Numeric IDs - Use numeric type for IDs when possible
  8. Batch Operations - Use batch insert for importing large datasets
  9. Indexing - Tables are automatically indexed on row ID
  10. Data Validation - All data is validated against field schemas before insert

Limitations

  • No Schema Updates: Cannot modify table structure after creation
  • Admin/Owner Only: All operations require elevated permissions
  • Row ID: Each row has an auto-generated numeric id (not customizable)
  • No Joins: Each table is independent (no foreign key relationships)
  • No Computed Fields: All fields must be explicitly provided
  • Filter Complexity: Maximum 10 filters per query recommended

Common Issues

Issue Solution
Table creation fails Check table name is unique and lowercase
Insert fails validation Verify all required fields are provided
Filter not working Check field name spelling and operator syntax
Cannot update table Tables cannot be modified - create a new one
Permission denied Ensure user has Admin or Owner role
Row not found Verify row ID exists in table

Data Types Details

text

Stores string data. No length limit.

numeric

Stores numbers. Can be integers or decimals.

{ "price": 99.99 }
{ "quantity": 5 }

boolean

Stores true or false.

{ "is_active": true }

timestamp

Stores ISO 8601 formatted timestamps.

{ "created_at": "2024-01-01T12:00:00Z" }

jsonb

Stores JSON objects. Supports nested structures.

{
  "metadata": {
    "tags": ["featured", "sale"],
    "attributes": {
      "color": "blue",
      "size": "large"
    }
  }
}