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

# Smart Tables

> Store your own structured data in typed tables, let agents search it, and push rows through the API

Smart Tables hold your own structured data, such as invoices, products or contracts, in typed columns. Agents can search them by meaning and filter or sort them by column, and your systems can push rows through the Public API.

Smart tables are under **Developer** > **Data** > **Smart tables**.

## Table Structure

Each smart table has:

* A **schema** of typed columns you define (`text`, `integer`, `bigint`, `numeric`, `boolean`, `date`, `timestamp`, `text_array`).
* A **slug** used to reference it in API calls.
* Optional **searchable fields**: the text columns used for semantic search.
* An optional **label field** used as the row's name in agent answers and in the admin interface.

Rows are identified by an `external_id` you control, so upserts replace existing rows with the same id.

## Creating a Smart Table

Navigate to **Developer** > **Data** > **Smart tables** and click **Create**, then:

1. Set a name and optional description.
2. Add columns (name + type). After creation, you can add columns but not change or remove existing ones.
3. Choose which columns are searchable.
4. Pick a label field.

Once created, you can view rows, add rows manually, upload a PDF to extract a row automatically, or push rows through the API.

You can also ask the AGO Assistant to create a Smart Table. Specify its name, optional slug, columns and types, searchable fields, and label field. The assistant opens the creation form, fills it, and can save it on request.

To add a row, tell the assistant which table to open and provide the field values. It opens the row panel, fills the visible fields, and saves on request. Supply both the technical `external_id` and any required column. Adding a row checks for an existing external ID before saving and reports missing fields or save errors.

## Adding a Row from a PDF

From the rows view of any smart table, click **Add file** and pick a PDF. AGO reads the document, fills in the table's columns based on the schema, and inserts a new row with the extracted values.

To steer how AGO reads your documents, set the table's **Extraction prompt** on its schema page, for example "Extract values from a sales invoice". Leave it blank to use a generic default.

## Clearing All Rows

From the rows view, click **Clear table** in the header and confirm. Every row in the table is permanently deleted. The schema, columns, and extraction prompt are kept — only the data is removed. This action cannot be undone.

## Browsing Rows

The rows view offers three ways to narrow down the data you see:

* **Semantic search** — type into the search box to rank rows by meaning.
* **Filters** — click **More filters** to pick a column (external\_id, created\_at, updated\_at, or any of your custom columns). The input that appears depends on the column type: text boxes for text or numeric columns, true/false for booleans, date range pickers for dates. Active filters stay visible until you clear them.
* **Sort** — click any column header to sort ascending, click again for descending, click a third time to clear.

Sorting is disabled while a semantic search is active, because results are already ranked by relevance.

## Pushing Data via API

From the rows view of any smart table, click **Push via API** to see a ready-to-copy `curl` example pre-filled with the table slug and a sample row matching your schema.

### Authentication

Push endpoints use scoped API key authentication. Create an API key under **Developer** > **API Keys** with the `custom_data_sources:write` scope (or `custom_data_sources:read` for read-only access). See [Public API v1](https://ago.mintlify.site/api/public-api-v1.md) for auth details.

### Upsert Rows

```bash theme={null}
curl -X POST 'https://your-workspace.api.useago.com/api/v1/custom-data-sources/<slug>/rows' \
  -H 'X-API-Key: ago_v1_sk_your_key_here' \
  -H 'Content-Type: application/json' \
  -d '{
    "rows": [
      {
        "external_id": "row-1",
        "data": { "amount": 42, "name": "example" },
        "tags": [],
        "metadata": {}
      }
    ]
  }'
```

Rows are upserted by `external_id`: existing rows are replaced, new ones are inserted. The `data` keys must match the table schema.

To control exactly what semantic search matches against, set `searchable_text` on the row. It replaces the combination of the table's searchable fields for that row.

```bash theme={null}
curl -X POST 'https://your-workspace.api.useago.com/api/v1/custom-data-sources/<slug>/rows' \
  -H 'X-API-Key: ago_v1_sk_your_key_here' \
  -H 'Content-Type: application/json' \
  -d '{
    "rows": [
      {
        "external_id": "row-1",
        "data": { "amount": 42, "name": "example" },
        "searchable_text": "Custom hand-crafted blurb used verbatim for semantic search"
      }
    ]
  }'
```

You can also set `content` on the row: free-form text, typically markdown, shown on the row's viewer page. PDF uploads fill `content` automatically with the document's text.

### Upload a PDF

Send a PDF as `multipart/form-data`. AGO runs the extraction described in [Adding a Row from a PDF](#adding-a-row-from-a-pdf), and inserts the resulting row.

```bash theme={null}
curl -X POST 'https://your-workspace.api.useago.com/api/v1/custom-data-sources/<slug>/upload' \
  -H 'X-API-Key: ago_v1_sk_your_key_here' \
  -F 'file=@/path/to/invoice.pdf'
```

On success the endpoint returns `201 Created` with the inserted row:

```json theme={null}
{
  "id": "01HX…",
  "external_id": "invoice.pdf:9f1c2a3b4d5e6f70",
  "data": {
    "amount": 1250,
    "issued_on": "2025-04-01",
    "vendor": "ACME",
    "__metadata__": { "source_file": "invoice.pdf" }
  },
  "tags": [],
  "searchable_text": "ACME 1250 …",
  "content": "# Invoice ACME\n…(full extracted markdown)…",
  "updated_at": "2025-04-01T12:00:00Z",
  "score": null
}
```

Notes:

* One PDF per request, one row inserted per call.
* The `external_id` defaults to `<filename>:<sha256-prefix>`, so uploading the same file again overwrites the same row instead of creating a duplicate.
* The original filename is exposed on the response at `data.__metadata__.source_file`.
* To steer the extraction, set the smart table's **extraction prompt** on its schema page (see [Adding a Row from a PDF](#adding-a-row-from-a-pdf)).

Common errors:

| Status | Meaning |
| - | - |
| `401` | Missing or invalid `X-API-Key` |
| `403` | API key lacks the `custom_data_sources:write` scope |
| `404` | No smart table matches `<slug>` |
| `422` | The uploaded file is missing or unreadable |

### Other Endpoints

| Method | Path | Scope | Purpose |
| - | - | - | - |
| `GET` | `/api/v1/custom-data-sources` | `custom_data_sources:read` | List smart table summaries, including column and row counts |
| `POST` | `/api/v1/custom-data-sources` | `custom_data_sources:write` | Create a smart table |
| `GET` | `/api/v1/custom-data-sources/{id_or_slug}` | `custom_data_sources:read` | Get a smart table with its schema definition |
| `PUT` | `/api/v1/custom-data-sources/{id_or_slug}` | `custom_data_sources:write` | Update a smart table and add columns |
| `DELETE` | `/api/v1/custom-data-sources/{id_or_slug}` | `custom_data_sources:write` | Delete a smart table and its rows |
| `POST` | `/api/v1/custom-data-sources/{slug}/rows` | `custom_data_sources:write` | Upsert rows |
| `POST` | `/api/v1/custom-data-sources/{slug}/rows/delete` | `custom_data_sources:write` | Delete rows by `external_id` |
| `POST` | `/api/v1/custom-data-sources/{slug}/rows/clear` | `custom_data_sources:write` | Delete every row in the table (schema preserved) |
| `POST` | `/api/v1/custom-data-sources/{slug}/rows/search` | `custom_data_sources:read` | Search rows (semantic + filters) |
| `GET` | `/api/v1/custom-data-sources/{slug}/rows/{external_id}` | `custom_data_sources:read` | Fetch a single row |
| `POST` | `/api/v1/custom-data-sources/{slug}/upload` | `custom_data_sources:write` | Upload a PDF and extract a row matching the schema |

## Using Smart Tables in Agents

Agents search smart tables through a tool. In **AI Studio** → **Tools**, create a tool of type `custom_data_source_search`, select the table in **Datasource**, and assign the tool to an agent. See [Tools](https://ago.mintlify.site/features/tools.md).

When you configure the tool, you choose:

* **Filterable columns** — columns the agent may filter on (it picks the operator at call time: `eq`, `gt`, `lt`, `contains`, etc.).
* **Sortable columns** — columns the agent may sort by. Enable these so the agent can answer "top/largest" or "smallest/lowest" questions, like "give me the 5 invoices with the largest amount". The agent automatically picks the direction (descending for "largest/highest/top", ascending for "smallest/lowest"). Sort is ignored when the agent runs a semantic search, since results are already ranked by relevance.

By default, when a matching row has `content`, the full content is included in the search results so the agent can read the whole document. If the content is large, check **Exclude full row content** in the tool configuration: the results then keep each row's column values and a link to the full content, without the content text itself.


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