airtable
airtable.
A row in an Airtable table: list, read, create, update, upsert, delete.
setup & usage
⚠ airtable personal access token
create a personal access token at airtable.com/create/tokens, then paste it into oto (it starts with pat…).
1. scopes: data.records:read + data.records:write, data.recordComments:read + data.recordComments:write, schema.bases:read + schema.bases:write
2. access: explicitly add each base (or the whole workspace) that the token must see
200 with an empty list, never an error: oto's "test connection" button detects it and says so▸ read and write in a base
airtable_base() (returns the appXXXXXXXX — the starting point for everything else)airtable_table(base_id="app…") (tables, fields, types, options, views)airtable_field(base_id="app…", table_id="tbl…")airtable_record(base_id="app…", table="tbl…", filter_by_formula="{Status}='Done'")airtable_record(op="create", records=[{"Name": "…", "Email": "…"}, …]) (split into batches of 10 automatically)airtable_record(op="upsert", records=[…], merge_on=["Email"])airtable_record(op="update", record_id="rec…", fields={"Status": "Signed"})airtable_comment(op="create", base_id=…, table=…, record_id=…, text="follow-up sent")airtable_attachment(base_id=…, record_id=…, field="Attachments", filename="quote.pdf", content_type="application/pdf", file_base64=…)airtable_table(op="create", name="Tracking", fields=[{"name": "Name", "type": "singleLineText"}, {"name": "Status", "type": "singleSelect", "options": {"choices": [{"name": "To do"}, {"name": "Done"}]}}])· names vs identifiers, typecast, batches
tbl…, fld… are stable; a table or column name changes as soon as someone renames it in the interface, and the automation silently breaks. airtable_table and airtable_field return the identifiers.typecast=True when you WANT this behavior.aborted: "rate_limit" and the number of rows actually written — retry 30 seconds later with the rest.airtable_record follows pagination up to max_records (100 by default) and sets more: true + offset if rows remain. nothing is silently truncated.airtable_record(op="update", fields={"Attachments": [{"url": "https://…"}]}). airtable fetches it itself.airtable_record(op="create").DELETE (404), no table deletion, and a field PATCH carrying options is refused (422 "Changing a field's type or number precision is not currently supported"). in practice: a select option created by mistake with typecast=True can ONLY be removed in the Airtable interface. one more reason to leave typecast false.airtable_base(op="create") has no counterpart, it is done in the interface.⚙ multiple comptes
this connector accepts multiple comptes: each stored credential becomes a named account (one name per compte), at your level, your team's or your org's.
_account="<name>" on the tool; list them: oto_identity(op='list', connector='airtable') (scope='org' or scope='group' for the org's or team's)oto_identity(op='set', connector='airtable', identity_id='<name>'); rename: op='rename' with new_name_account) and adding upoutils
chargement…
utilisation
claude code — installe le plugin oto —
claude plugin marketplace add otomata-tech/oto-plugin — mcp + skill configurés.cli —
pipx install oto-cli puis oto airtable …