Airtable bindings — the lightweight database half the world runs ops on. Records CRUD with formula filtering, batch upsert/delete, record comments, plus the metadata API for base schemas and token identity.

Setup — context variable airtable.token: a personal access token (pat...) with the scopes and bases it needs.

Quick start

::at ::airtable

rows ::at/list-records(base-id, "Leads", {
  filterByFormula: "AND({Status} = 'New', {Score} > 50)",
  maxRecords: 20
})

::at/create-records(base-id, "Leads", [
  {fields: {Name: "Ada Lovelace", Status: "New", Score: 99}}
])

Values

BASE_URL

BASE_URL: Str "https://api.airtable.com/v0"

Functions

comments-path

fn (base-id: Str, table: Str, record-id: Str): Str

create-comment

fn (base-id: Str, table: Str, record-id: Str, text: Str): Map

POST /{base}/{table}/{record}/comments - Comment on a record. @[userId] mentions work inside text.

create-records

fn (base-id: Str, table: Str, records: Vec): Map

POST /{base}/{table} - Create up to 10 records: [{fields: {...}}]. typecast is enabled so string inputs coerce to the field types.

delete-comment

fn (base-id: Str, table: Str, record-id: Str, comment-id: Str): Map

DELETE /{base}/{table}/{record}/comments/{comment} - Delete a comment (author-owned comments only).

delete-record

fn (base-id: Str, table: Str, record-id: Str): Map

DELETE /{base}/{table}/{id} - Delete one record.

delete-records

fn (base-id: Str, table: Str, record-ids: Vec): Map

DELETE /{base}/{table}?records[]= - Delete up to 10 records in one call. Returns {records: [{id, deleted}]}.

escape-formula-value

fn (value: Str): Str

Escape a value for interpolation into an Airtable formula as a single-quoted string literal (backslashes and quotes escaped, quotes included). Always use this when building filterByFormula from user or agent input — unescaped interpolation lets crafted input rewrite the formula.

Example

formula `{Email} = ${::airtable/escape-formula-value(input)}`
::airtable/list-records(base, "Leads", {filterByFormula: formula})

get-base-schema

fn (base-id: Str): Map

GET /meta/bases/{base}/tables - The base's tables, fields, and views — what an agent reads before writing records.

get-record

fn (base-id: Str, table: Str, record-id: Str): Map

GET /{base}/{table}/{id} - One record ({id, createdTime, fields}).

list-bases

fn (): Map

GET /meta/bases - The bases the token can access.

list-comments

fn (base-id: Str, table: Str, record-id: Str): Map
fn (base-id: Str, table: Str, record-id: Str, params: Map): Map

GET /{base}/{table}/{record}/comments - A record's comments ({comments, offset?}). params (4-arity): pageSize (max 100), offset.

list-records

fn (base-id: Str, table: Str): Map
fn (base-id: Str, table: Str, params: Map): Map

GET /{base}/{table} - List records. params: filterByFormula (Airtable formula), maxRecords, view, sort handled by formula, offset (paging cursor from the previous page). Returns {records, offset?}.

Context Vars: airtable.token

records-query

fn (record-ids: Vec): Str

Build the repeated records[]= query string batch deletion needs (query-string can't express repeated keys). Exposed for testing; delete-records uses it.

request

fn (method: Str, path: Str, body: Any): Any
fn (method: Str, path: Str, body: Any, token: Str): Any

table-path

fn (base-id: Str, table: Str): Str

update-comment

fn (base-id: Str, table: Str, record-id: Str, comment-id: Str, text: Str): Map

PATCH /{base}/{table}/{record}/comments/{comment} - Edit a comment's text (author-owned comments only).

update-records

fn (base-id: Str, table: Str, records: Vec): Map

PATCH /{base}/{table} - Update up to 10 records: [{id, fields}] (only the given fields change).

upsert-records

fn (base-id: Str, table: Str, merge-fields: Vec, records: Vec): Map

PATCH /{base}/{table} with performUpsert - Create-or-update up to 10 records keyed on merge-fields (field names that uniquely identify a record). Records are [{fields: {...}}] — no ids. Returns {records, createdRecords, updatedRecords}.

Example

::airtable/upsert-records(base-id, "Leads", ["Email"], [
  {fields: {Email: "ada@example.com", Status: "Customer"}}
])

whoami

fn (): Map

GET /meta/whoami - The token's own user id and granted scopes. The cheapest way to smoke-test a token.