Live table vs frozen table
Columns
GET /v1/tables/{id} returns columns in order:
key in your code; name is for display. links.app opens the table in the Retriever app (session required). Table lists and table imports return the same link.
In a live table (/v1/tables/{id}), a column hidden in the app is not returned, and its values are not in the rows. Cell explanations (stale_because, skipped, the message of a skipped cell, the reason of a verdict reset by a dependency change) do not name it either: a value made stale only by hidden columns has an empty stale_because, and is still stale. It stays in the table: showing it again in the app brings it back in the API. To read it anyway, add include_hidden=true to GET /v1/tables/{id}, GET /v1/tables/{id}/rows or GET /v1/workspaces/{id}/tables: hidden columns come back with hidden: true, and their values are in the rows. next_cursor does not carry the option: send include_hidden=true with every page.
A run output is a frozen copy. When the agent maps its columns, the output holds exactly those, in that order. Without a mapping, it holds the table’s columns in the order shown in the app, minus the columns hidden when the run delivered it, unless your row_schema names them. A name counts in properties, required, dependencies, the branches of allOf, anyOf, oneOf and if/then/else, and #/ references; a required column the schema reaches another way is added when the check reports it missing. Cell explanations (stale_because, skipped, the message of a skipped cell, the reason of a verdict reset by a dependency change) do not name a hidden column the output leaves out. include_hidden does not apply to run outputs.
Rows
A
null value is not enough: read status to distinguish “not found” (no_result) from “in progress” (running).Import a list
POST /v1/workspaces/{id}/tables creates a table with your columns and rows in a single transaction: one error rolls back the entire import.
- A missing property becomes
null. Row and column order is preserved. - Created columns are
fieldtype. - A table does not accept rows after creation: create a new table per batch.
- Creation is not idempotent: each call creates a new table.
- More than 200 columns or 10,000 rows returns
400 invalid_request. Nothing is written. Split a larger list into several tables. - The request body can be at most 25 MiB (26,214,400 bytes). A larger body returns
413 body_too_large. - The response is the table. Its
links.appopens the new table in the Retriever app (session required).