Skip to content

Table APIs

Every table has its own API: a URL, by an opaque key, that answers its rows as JSON, CSV, NDJSON or Parquet. Find it in the panel that the table’s API button opens in the app.

  • https://api.rho.store/v/<key>: the latest version, a page of rows as JSON objects.
  • https://api.rho.store/v/<key>@3: version 3, for good. This always needs an API token.
  • https://api.rho.store/v/<key>.csv: every row of the version, as a file. Also .ndjson and .parquet.

Any table answers an API token of its workspace:

curl -H "Authorization: Bearer $RHO_API_KEY" https://api.rho.store/v/<key>

Once a table is public, the same URL also answers anyone who has it, with no token. They get the latest version only: @3 still needs a token of the workspace, as an old version may hold what you removed before making the table public.

Replacing a table’s links, in its Share panel, makes a new key. The old URL stops working for good, also for callers with a token.

A JSON page answers the rows as objects, typed as the table is: numbers are numbers, dates and times are ISO text, and an empty cell is null. Cells are never cut short.

{
"table": "research/competitors",
"version": 7,
"columns": [{ "name": "company", "type": "VARCHAR" }],
"rows": [{ "company": "Neon" }],
"offset": 0,
"total": 214,
"next": "https://api.rho.store/v/<key>?offset=100"
}

total counts the rows that match, all pages together. next is the URL of the next page, and null on the last.

ParameterWhat it does
?country=SERows whose country is SE
?price__gt=10Compare a column: __eq, __ne, __contains, __gt, __lt, __gte, __lte, __empty, __not_empty
?sort=price, ?sort=-priceOrder by a column, - for descending
?select=company,priceOnly these columns, in this order
?q=vectorRows with this text in any column
?limit=, ?offset=The page’s size (100 rows unless you say, 500 at most) and start

A column named like one of these parameters is filtered with __eq, as in ?sort__eq=x. These are for JSON pages: a .csv, .ndjson or .parquet is every row of the version, and turns down a query.

Every answer has an X-Rho-Version header and an ETag. Send the ETag back as If-None-Match, and you get 304 Not Modified until the table has a new version. A pinned version (@3) never changes, so it can be cached.

The key follows the table through a rename. CORS is open on /v/, so a public table can be read from a browser.