Skip to main content
A table holds companies or contacts. Runs create or enrich it; you can also import your own lists.

Live table vs frozen table

Columns

GET /v1/tables/{id} returns columns in order:
Use 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 field type.
  • 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.app opens the new table in the Retriever app (session required).
See Enrich a list from your CRM for a full example.