Skip to content
Browse the docs

Tables API

Updated

On this page

Available on the demo and in OneCamp Cloud now. Self-hosted installs get the rows, trash and history calls with their next update, and the fields, views and comments calls with a later update.

Base URL: https://<your workspace's API host>/v1. Every call sends Authorization: Bearer oc_… (a personal, agent or app token) and acts with the token's member's access, never more, and never with an admin's powers. The machine-readable contract is GET /v1/openapi.json.

Scopes

Scope What it allows
tables:read Read the tables you can open
tables:write Add and change rows in the tables you can edit

A token holds only the scopes it was made with; a call outside them is a 403 forbidden. Writes that change a table's fields or shared views also need the member to manage the table, as in the app.

Rows

Read a table's rows as its views do, a row or rows by id, and write them one at a time or in one batch. Every write is one change set in the table's history; a delete moves the row to the trash.

Tables, rows and totals

GET /v1/tables

scope tables:read

The tables you can open.

GET /v1/tables/{id}

scope tables:read

A table: its fields and rows.

POST /v1/tables/{id}/rows

scope tables:write

Add a row; the answer names the change set it stored.

POST /v1/tables/{id}/aggregate

scope tables:read

Sums, counts and averages over a table.

Operations

tables.rows.query

POST /v1/tables/{id}/rows/query · scope tables:read · reads only, the same call twice has the effect of one

A table's rows, filtered, sorted and searched as a view does, a page at a time.

  • Spends one of the token's row budget for each row it names (see Limits). MCP: the same op is the tool of the same name, with the same scope and arguments, in the AI edition.
Argument In Type Required Limits What it is
id path string yes at most 64 chars The table's id.
filter body any no Which rows: a view's filter, conditions in groups. Leave it out for every row.
sorts body array of object no at most 10 items
search body string no at most 200 chars Words a row's cells hold.
cursor body string no at most 4096 chars The next_cursor of the page before.
limit body integer no ≥ 1; ≤ 200 Rows a page, 50 when left out.
tz body string no at most 64 chars An IANA time zone, where a formula's TODAY() is.

Each item of sorts:

Key Type Required Limits What it is
field string yes at most 64 chars
desc boolean no

tables.row.get

GET /v1/tables/{id}/rows/{row} · scope tables:read · reads only, the same call twice has the effect of one

A row by its id, as it is now; its version is the ETag a change's If-Match names.

  • The answer carries the row's version as its ETag; send it back as If-Match and a change made since is refused with 412 version_mismatch, not overwritten.
  • Spends one of the token's row budget. MCP: the same op is the tool of the same name, with the same scope and arguments, in the AI edition.
Argument In Type Required Limits What it is
id path string yes at most 64 chars The table's id.
row path string yes at most 64 chars The row's id.

tables.rows.get

POST /v1/tables/{id}/rows/get · scope tables:read · reads only, the same call twice has the effect of one

Rows of a table by their ids, in the order named; a row deleted or not the table's is left out.

  • Spends one of the token's row budget for each row it names (see Limits). MCP: the same op is the tool of the same name, with the same scope and arguments, in the AI edition.
Argument In Type Required Limits What it is
id path string yes at most 64 chars The table's id.
ids body array of string yes at least 1 items; at most 500 items The rows' ids.

tables.row.update

PATCH /v1/tables/{id}/rows/{row} · scope tables:write · writes, the same call twice has the effect of one, recoverable

Change some cells of a row and leave the rest as they are; the answer names the change set it stored (null if it changed nothing), as the row's history lists it.

  • Send an Idempotency-Key header: the same key with the same body within 24 hours is answered once, from the first answer.
  • The answer carries the row's version as its ETag; send it back as If-Match and a change made since is refused with 412 version_mismatch, not overwritten.
  • Taken back by: tables.row.history, tables.row.update.
  • Spends one of the token's row budget. MCP: the same op is the tool of the same name, with the same scope and arguments, in the AI edition.
Argument In Type Required Limits What it is
id path string yes at most 64 chars The table's id.
row path string yes at most 64 chars The row's id.
values body object yes Each field's id and its new value; null clears it.
version body integer no ≥ 1 The row's version as it was read (If-Match): a row changed since is refused.

tables.rows.batch

POST /v1/tables/{id}/rows/batch · scope tables:write · writes, may remove or overwrite, recoverable

Make, change and delete rows of a table in one change: all of it is written, or none and the rows refused are named.

  • Send an Idempotency-Key header: the same key with the same body within 24 hours is answered once, from the first answer.
  • Taken back by: tables.row.delete, tables.row.history, tables.row.update, tables.trash.restore.
  • Spends one of the token's row budget for each row it names (see Limits). MCP: the same op is the tool of the same name, with the same scope and arguments, in the AI edition.
Argument In Type Required Limits What it is
id path string yes at most 64 chars The table's id.
create body array of object no at most 1000 items Rows to make.
update body array of object no at most 1000 items Rows to change: the cells named, the rest as they are.
delete body array of string no at most 1000 items Rows to move to the trash.
after body string no at most 64 chars New rows go after this row; with neither after nor before, after the last.
before body string no at most 64 chars New rows go before this row.

Each item of create:

Key Type Required Limits What it is
values object yes Each field's id and its value.

Each item of update:

Key Type Required Limits What it is
row string yes at most 64 chars The row's id.
values object yes Each field's id and its new value; null clears it.
version integer no ≥ 1 The row's version as it was read: a row changed since refuses the batch.

tables.row.delete

DELETE /v1/tables/{id}/rows/{row} · scope tables:write · writes, may remove or overwrite, the same call twice has the effect of one, recoverable

Move a row to its table's trash, from where it can be brought back.

  • Send an Idempotency-Key header: the same key with the same body within 24 hours is answered once, from the first answer.
  • Taken back by: tables.trash.restore.
  • Spends one of the token's row budget. MCP: the same op is the tool of the same name, with the same scope and arguments, in the AI edition.
Argument In Type Required Limits What it is
id path string yes at most 64 chars The table's id.
row path string yes at most 64 chars The row's id.

Trash and history

What was deleted waits in the table's trash: rows, fields and views, each brought back as it was. A row's history lists every change, who made it and how (the app, a token, an agent).

tables.trash.list

GET /v1/tables/{id}/trash · scope tables:read · reads only, the same call twice has the effect of one

A table's trash: its deleted rows, newest first, a page at a time, its deleted fields for those who manage it, and its deleted views the caller may bring back.

  • Spends one of the token's row budget for each row it names (see Limits). MCP: the same op is the tool of the same name, with the same scope and arguments, in the AI edition.
Argument In Type Required Limits What it is
id path string yes at most 64 chars The table's id.
cursor query string no at most 64 chars The next_cursor of the page before.

tables.trash.restore

POST /v1/tables/{id}/trash/restore · scope tables:write · writes, the same call twice has the effect of one, recoverable

Bring rows, fields and views back from a table's trash, rows and fields with their cells and links.

  • Send an Idempotency-Key header: the same key with the same body within 24 hours is answered once, from the first answer.
  • Taken back by: tables.field.delete, tables.row.delete, tables.view.delete.
  • Spends one of the token's row budget for each row it names (see Limits). MCP: the same op is the tool of the same name, with the same scope and arguments, in the AI edition.
Argument In Type Required Limits What it is
id path string yes at most 64 chars The table's id.
rows body array of string no at most 1000 items Rows to bring back.
fields body array of string no at most 1000 items Fields to bring back: for those who manage the table.
views body array of string no at most 1000 items Views to bring back: one's own, and shared ones for those who manage the table.

tables.row.history

GET /v1/tables/{id}/rows/{row}/history · scope tables:read · reads only, the same call twice has the effect of one

A row's history, newest first, a page at a time: each change, who made it and how, and its cells before and after.

  • Spends one of the token's row budget for each row it names (see Limits). MCP: the same op is the tool of the same name, with the same scope and arguments, in the AI edition.
Argument In Type Required Limits What it is
id path string yes at most 64 chars The table's id.
row path string yes at most 64 chars The row's id.
cursor query string no at most 64 chars The next_cursor of the page before.

Fields

A table's fields (columns): list, add, change and move to the trash, one at a time or in one batch. The app's own checks apply: names, kinds, formulas, links and rollups.

tables.fields.list

GET /v1/tables/{id}/fields · scope tables:read · reads only, the same call twice has the effect of one

A table's fields: each one's id, name, kind, settings and place.

  • Spends one of the token's row budget. MCP: the same op is the tool of the same name, with the same scope and arguments, in the AI edition.
Argument In Type Required Limits What it is
id path string yes at most 64 chars The table's id.

tables.field.create

POST /v1/tables/{id}/fields · scope tables:write · writes, recoverable

Add a field to a table, for those who manage it; the answer is the field.

  • Send an Idempotency-Key header: the same key with the same body within 24 hours is answered once, from the first answer.
  • Taken back by: tables.field.delete.
  • Spends one of the token's row budget. MCP: the same op is the tool of the same name, with the same scope and arguments, in the AI edition.
Argument In Type Required Limits What it is
id path string yes at most 64 chars The table's id.
name body string yes at most 120 chars The field's name.
type body string no at most 32 chars Its kind (text, number, select, date, checkbox, formula, relation, rollup and the rest the reference lists); text when a create leaves it out.
config body object no Its settings as its kind reads them: a select's options, a number's format, a formula's text, a link's table.
description body string no at most 2000 chars What the field is for.
required body boolean no Whether every row made through the API, an AI tool or a form must give it.
default_value body any no What a new row's cell starts as; null is none.
position body number no Its place among the columns: lower is further left.

tables.field.update

PATCH /v1/tables/{id}/fields/{field} · scope tables:write · writes, the same call twice has the effect of one, recoverable

Change a field's settings, and its cells with its kind or options; what's left out stays as it is.

  • Send an Idempotency-Key header: the same key with the same body within 24 hours is answered once, from the first answer.
  • Taken back by: tables.field.update, tables.row.history, tables.row.update.
  • Spends one of the token's row budget. MCP: the same op is the tool of the same name, with the same scope and arguments, in the AI edition.
Argument In Type Required Limits What it is
id path string yes at most 64 chars The table's id.
field path string yes at most 64 chars The field's id.
name body string no at most 120 chars The field's name.
type body string no at most 32 chars Its kind (text, number, select, date, checkbox, formula, relation, rollup and the rest the reference lists); text when a create leaves it out.
config body object no Its settings as its kind reads them: a select's options, a number's format, a formula's text, a link's table.
description body string no at most 2000 chars What the field is for.
required body boolean no Whether every row made through the API, an AI tool or a form must give it.
default_value body any no What a new row's cell starts as; null is none.
position body number no Its place among the columns: lower is further left.
primary body boolean no true makes it the field naming the table's rows; another field becoming primary is how one stops being it.
decimal body string no at most 1 chars How text in a column made numbers writes its decimal sign; a point when left out.
group body string no at most 1 chars How such text writes the sign between thousands; a comma when left out.

tables.field.delete

DELETE /v1/tables/{id}/fields/{field} · scope tables:write · writes, may remove or overwrite, the same call twice has the effect of one, recoverable

Move a field to its table's trash, with its cells, from where it can be brought back.

  • Send an Idempotency-Key header: the same key with the same body within 24 hours is answered once, from the first answer.
  • Taken back by: tables.trash.restore.
  • Spends one of the token's row budget. MCP: the same op is the tool of the same name, with the same scope and arguments, in the AI edition.
Argument In Type Required Limits What it is
id path string yes at most 64 chars The table's id.
field path string yes at most 64 chars The field's id.

tables.fields.batch

POST /v1/tables/{id}/fields/batch · scope tables:write · writes, may remove or overwrite, the same call twice has the effect of one, recoverable

Add, change and delete a table's fields in one call: every item is checked first and one refused refuses the call; then they are applied one by one in order, so a failure part way names the items done, and the same call sent again with its key does the rest.

  • Send an Idempotency-Key header: the same key with the same body within 24 hours is answered once, from the first answer.
  • Taken back by: tables.field.delete, tables.field.update, tables.row.history, tables.row.update, tables.trash.restore.
  • Spends one of the token's row budget for each row it names (see Limits). MCP: the same op is the tool of the same name, with the same scope and arguments, in the AI edition.
Argument In Type Required Limits What it is
id path string yes at most 64 chars The table's id.
key body string yes at least 1 chars; at most 200 chars Names this batch: the same batch sent again with the same key skips the items it did and answers them as before. A new batch takes a new key.
create body array of object no at most 100 items Fields to add, applied first.
update body array of object no at most 100 items Fields to change, applied next.
delete body array of string no at most 100 items Fields to move to the trash, applied last.

Each item of create:

Key Type Required Limits What it is
name string yes at most 120 chars The field's name.
type string no at most 32 chars Its kind (text, number, select, date, checkbox, formula, relation, rollup and the rest the reference lists); text when a create leaves it out.
config object no Its settings as its kind reads them: a select's options, a number's format, a formula's text, a link's table.
description string no at most 2000 chars What the field is for.
required boolean no Whether every row made through the API, an AI tool or a form must give it.
default_value any no What a new row's cell starts as; null is none.
position number no Its place among the columns: lower is further left.

Each item of update:

Key Type Required Limits What it is
field string yes at most 64 chars The field's id.
name string no at most 120 chars The field's name.
type string no at most 32 chars Its kind (text, number, select, date, checkbox, formula, relation, rollup and the rest the reference lists); text when a create leaves it out.
config object no Its settings as its kind reads them: a select's options, a number's format, a formula's text, a link's table.
description string no at most 2000 chars What the field is for.
required boolean no Whether every row made through the API, an AI tool or a form must give it.
default_value any no What a new row's cell starts as; null is none.
position number no Its place among the columns: lower is further left.
primary boolean no true makes it the field naming the table's rows; another field becoming primary is how one stops being it.
decimal string no at most 1 chars How text in a column made numbers writes its decimal sign; a point when left out.
group string no at most 1 chars How such text writes the sign between thousands; a comma when left out.

Views

A table's saved views: shared ones (its managers') and each reader's own. List, add, change, and move to the trash, one at a time or in one batch; a locked view is refused.

tables.views.list

GET /v1/tables/{id}/views · scope tables:read · reads only, the same call twice has the effect of one

A table's views the caller sees: the shared ones and their own, each with its settings.

  • Spends one of the token's row budget. MCP: the same op is the tool of the same name, with the same scope and arguments, in the AI edition.
Argument In Type Required Limits What it is
id path string yes at most 64 chars The table's id.

tables.view.create

POST /v1/tables/{id}/views · scope tables:write · writes, recoverable

Add a view to a table: one of the caller's own, or a shared one for those who manage it; the answer is the view.

  • Send an Idempotency-Key header: the same key with the same body within 24 hours is answered once, from the first answer.
  • Taken back by: tables.view.delete.
  • Spends one of the token's row budget. MCP: the same op is the tool of the same name, with the same scope and arguments, in the AI edition.
Argument In Type Required Limits What it is
id path string yes at most 64 chars The table's id.
name body string no at most 120 chars The view's name.
type body string no at most 32 chars grid, board, calendar, chart, gallery, form, timeline or list; grid when a create leaves it out.
config body object no Its settings: filter, sorts, groups, hidden fields and widths, as the app keeps them.
position body number no Its place among the table's views.
personal body boolean no true makes it the caller's own view, which anyone who reads the table may make; a shared view is its managers' to make.

tables.view.update

PATCH /v1/tables/{id}/views/{view} · scope tables:write · writes, the same call twice has the effect of one, recoverable

Change a view's name, kind, settings or place; what's left out stays as it is, and a locked view is refused.

  • Send an Idempotency-Key header: the same key with the same body within 24 hours is answered once, from the first answer.
  • Taken back by: tables.view.update.
  • Spends one of the token's row budget. MCP: the same op is the tool of the same name, with the same scope and arguments, in the AI edition.
Argument In Type Required Limits What it is
id path string yes at most 64 chars The table's id.
view path string yes at most 64 chars The view's id.
name body string no at most 120 chars The view's name.
type body string no at most 32 chars grid, board, calendar, chart, gallery, form, timeline or list; grid when a create leaves it out.
config body object no Its settings: filter, sorts, groups, hidden fields and widths, as the app keeps them.
position body number no Its place among the table's views.

tables.view.delete

DELETE /v1/tables/{id}/views/{view} · scope tables:write · writes, may remove or overwrite, the same call twice has the effect of one, recoverable

Move a view to its table's trash, from where it can be brought back; a locked view is refused.

  • Send an Idempotency-Key header: the same key with the same body within 24 hours is answered once, from the first answer.
  • Taken back by: tables.trash.restore.
  • Spends one of the token's row budget. MCP: the same op is the tool of the same name, with the same scope and arguments, in the AI edition.
Argument In Type Required Limits What it is
id path string yes at most 64 chars The table's id.
view path string yes at most 64 chars The view's id.

tables.views.batch

POST /v1/tables/{id}/views/batch · scope tables:write · writes, may remove or overwrite, the same call twice has the effect of one, recoverable

Add, change and delete a table's views in one call: every item is checked first and one refused refuses the call; then they are applied one by one in order, so a failure part way names the items done, and the same call sent again with its key does the rest.

  • Send an Idempotency-Key header: the same key with the same body within 24 hours is answered once, from the first answer.
  • Taken back by: tables.trash.restore, tables.view.delete, tables.view.update.
  • Spends one of the token's row budget for each row it names (see Limits). MCP: the same op is the tool of the same name, with the same scope and arguments, in the AI edition.
Argument In Type Required Limits What it is
id path string yes at most 64 chars The table's id.
key body string yes at least 1 chars; at most 200 chars Names this batch: the same batch sent again with the same key skips the items it did and answers them as before. A new batch takes a new key.
create body array of object no at most 100 items Views to add, applied first.
update body array of object no at most 100 items Views to change, applied next.
delete body array of string no at most 100 items Views to move to the trash, applied last.

Each item of create:

Key Type Required Limits What it is
name string no at most 120 chars The view's name.
type string no at most 32 chars grid, board, calendar, chart, gallery, form, timeline or list; grid when a create leaves it out.
config object no Its settings: filter, sorts, groups, hidden fields and widths, as the app keeps them.
position number no Its place among the table's views.
personal boolean no true makes it the caller's own view, which anyone who reads the table may make; a shared view is its managers' to make.

Each item of update:

Key Type Required Limits What it is
view string yes at most 64 chars The view's id.
name string no at most 120 chars The view's name.
type string no at most 32 chars grid, board, calendar, chart, gallery, form, timeline or list; grid when a create leaves it out.
config object no Its settings: filter, sorts, groups, hidden fields and widths, as the app keeps them.
position number no Its place among the table's views.

Comments

A row's comment threads, and new comments or replies, written as the token's member (an agent's token writes as its agent, on its member's behalf). Only the row's own threads are read or answered.

tables.row.comments.list

GET /v1/tables/{id}/rows/{row}/comments · scope tables:read · reads only, the same call twice has the effect of one

A row's comment threads, oldest first, each with its comments: the threads on the row and on its cells, open, resolved or both.

  • Spends one of the token's row budget. MCP: the same op is the tool of the same name, with the same scope and arguments, in the AI edition.
Argument In Type Required Limits What it is
id path string yes at most 64 chars The table's id.
row path string yes at most 64 chars The row's id.
status query string no one of open, resolved Only the open or only the resolved threads; both when left out.

tables.row.comment.create

POST /v1/tables/{id}/rows/{row}/comments · scope tables:write · writes

Comment on a row as the token's member: a new thread on the row or on one of its cells, or a reply in one of the row's threads.

  • Send an Idempotency-Key header: the same key with the same body within 24 hours is answered once, from the first answer.
  • Spends one of the token's row budget. MCP: the same op is the tool of the same name, with the same scope and arguments, in the AI edition.
Argument In Type Required Limits What it is
id path string yes at most 64 chars The table's id.
row path string yes at most 64 chars The row's id.
text body string yes at least 1 chars; at most 50000 chars The comment, as plain text: a blank line starts a paragraph, and lines that start with - or * make a list.
thread body string no at most 64 chars The id of one of the row's threads, to reply in it; leave it out to start a thread.
field body string no at most 64 chars A field's id, to start the thread on the row's cell in that field; leave it out for the row as a whole.

Limits

  • No cap per table or base. A token's calls are limited per token, never per table: Airtable's five requests a second per base has no counterpart.
  • Requests: each route allows 600 reads and 120 writes a minute per token by default; over it is a 429 rate_limited with Retry-After.
  • Row budget: a token reads up to 120,000 rows and writes up to 60,000 rows a minute, REST and MCP spending one counter. Each call spends what it reads or writes, a row at a time: a batch of a thousand rows spends a thousand; a call that names no rows spends one. Spent, it is a 429 row_budget with Retry-After.
  • Pages: lists take ?limit= 1 to 200 (50 when left out) and ?cursor= (the next_cursor of the page before); an answer with no next_cursor is the last page.
  • Batches: each op's limits are on its page (maxItems): rows by id and rows batches as the row ops say; fields and views batches at most 100 items each list. A fields or views batch takes a key: sent again with the same key, it skips the items it did and answers them as before.
  • Idempotency-Key: every write takes one. Kept 24 hours per token, key and route; the same key with another body is a 422 idempotency_key_reused; while the first is still being served, a 409 in_progress.
  • Versions: a row's read answers its version as ETag; a change with If-Match is refused with 412 version_mismatch when the row moved on.

Errors

Every error has one body:

{"error": {"code": "not_found", "message": "…", "hint": "…", "details": …}}

message says what happened; hint what to do; details appears when a refusal has parts to fix one by one:

  • a rows batch: one entry per refused row, {"index"?, "row"?, "field"?, "message"} (index: the create's place in create);
  • a fields or views batch: one entry per item, {"list", "index", "id"?, "message"} (list: create, update or delete). One refused item refuses the whole call, before anything is applied.
Status Code When
400 invalid_argument an argument breaks the op's schema or the app's own checks
400 conflicting_argument the body names a path parameter differently
400 unreadable_body the body isn't JSON
400 idempotency_key_too_long the key is too long (use a UUID)
401 unauthenticated no token, or one revoked or expired
403 forbidden the token's member lacks the access
403 not_for_apps / not_in_audience an app token outside the places an admin added it to
404 not_found the table, row, field or view isn't there for this member
409 locked a locked view
409 in_progress the same Idempotency-Key is still being served
410 gone it was deleted for good
412 version_mismatch If-Match names a version the row moved on from
422 idempotency_key_reused the same key with another body
429 rate_limited / row_budget over the route's limit or the token's row budget; see Retry-After
503 unavailable / working_out try again shortly
500 internal the server's fault, with a request id

Known exception: a call without a valid token, or with a token that lacks the route's scope, is refused before the op runs, and that refusal still has the older body {"error": true, "message": "…"} (401, and 403 "this token is missing the required scope: tables:write"). Read the status first.

Something missing or wrong in this guide? Write to support@onemana.dev.