# @kody/airtable ## Intent Provide reusable, account-agnostic Airtable helpers so Kody agents can read and update bases, tables, records, and comments through a saved `airtable` / `airtable-*` OAuth integration or a personal access token — without hand-rolling REST. Mutations are previewable with `dryRun: true` and only run live after `confirm: true`. This listing is meant to be forked. After you fork, connect **your** Airtable workspace. Do not treat the live `@kody/airtable` package storage as yours. Share this listing as https://kody.codes/@kody/airtable ## What it does - List or inspect bases, tables, records, and comments - Create, update, or delete records after explicit confirmation - Create comments after explicit confirmation - Call an unwrapped Airtable REST path through `./request` - Connect more than one Airtable account via `integrationName` / `account` ## Prerequisites / setup Airtable has **no built-in Kody OAuth app**. Choose one lane: | Lane | When to use | Credential | | --- | --- | --- | | **OAuth** (recommended) | Multi-account, refresh tokens, shared helpers | Saved integration `airtable` or `airtable-` | | **Personal access token** | Fastest for a single workspace / personal scripts | User secret `airtablePat` (or `airtablePat-`) | Both lanes send `Authorization: Bearer …`. Required API host: **`api.airtable.com`**. Approve it in the account secrets UI. ### Lane A — BYO OAuth 1. Register an OAuth integration at https://airtable.com/create/oauth 2. Set the redirect URI **exactly** to `https://kody.codes/connect/oauth` 3. Generate a **client secret** (Airtable token exchange uses HTTP Basic when a secret exists). Enable PKCE — Airtable requires S256 PKCE on every authorize request. 4. Under **Scopes**, enable the scopes this package uses (`data.records:read`, `data.records:write`, `data.recordComments:read`, `data.recordComments:write`, `schema.bases:read`). 5. Connect while signed in to Kody: https://kody.codes/connect/oauth?provider=airtable&authorizeUrl=https%3A%2F%2Fairtable.com%2Foauth2%2Fv1%2Fauthorize&tokenUrl=https%3A%2F%2Fairtable.com%2Foauth2%2Fv1%2Ftoken&apiBaseUrl=https%3A%2F%2Fapi.airtable.com%2Fv0&scopes=data.records%3Aread%20data.records%3Awrite%20data.recordComments%3Aread%20data.recordComments%3Awrite%20schema.bases%3Aread&flow=confidential&pkce=true&tokenExchangeStyle=basic-form&allowedHosts=api.airtable.com&dashboardUrl=https%3A%2F%2Fairtable.com%2Fcreate%2Foauth 6. Paste the Airtable client id and client secret into the Kody wizard (never into chat). Approve host `api.airtable.com`. 7. Reconnect later with https://kody.codes/connect/oauth?provider=airtable OAuth authorize URL: `https://airtable.com/oauth2/v1/authorize`. Token URL: `https://airtable.com/oauth2/v1/token`. Flow: confidential (client secret) plus S256 PKCE. Token exchange style: `basic-form`. Airtable scopes are **space-separated**. To connect a second workspace, change `provider` (for example `provider=airtable-work`) and pass `integrationName: 'airtable-work'` on every call. ### Lane B — Personal access token 1. Create a token at https://airtable.com/create/tokens 2. Grant the scopes above and add the bases this agent should see. 3. Save it (do not paste the value in chat): https://kody.codes/account/secrets/new?name=airtablePat&description=Airtable%20personal%20access%20token&allowedHosts=api.airtable.com&scope=user For a second workspace/token, use a distinct secret name such as `airtablePat-work` and pass `secretName: 'airtablePat-work'` (or `account: 'work'`, which resolves to `airtable-work` / `airtablePat-work`). ### Scopes | Scope | Needed for | | --- | --- | | `schema.bases:read` | list/get bases and tables | | `data.records:read` | list/get records | | `data.records:write` | create/update/delete records | | `data.recordComments:read` | list comments | | `data.recordComments:write` | create comments | `viewer` and `smoke-test` call `/meta/whoami`, which does not require a scope. This package does **not** request `user.email:read`. Agents: see [`AGENTS.md`](./AGENTS.md) for import paths, smoke, and dryRun. ## Done when - The `airtable` OAuth integration is connected **or** `airtablePat` is saved; host `api.airtable.com` is approved - Smoke test returns `{ ok: true }` (live whoami without email when credentials exist, or setup URLs when they do not) - Mutations refuse without `confirm: true`; `dryRun: true` never calls Airtable ## Branding The community icon is Airtable's official product mark as published at [https://airtable.com/images/favicon/mstile-144x144.png](https://airtable.com/images/favicon/mstile-144x144.png) (the current isometric logomark). Pixels are unmodified. Airtable® and the Airtable trademark are registered trademarks of Formagrid Inc dba Airtable. ## Docs - [Airtable Web API](https://airtable.com/developers/web/api/introduction) - [Authentication](https://airtable.com/developers/web/api/authentication) - [OAuth reference](https://airtable.com/developers/web/api/oauth-reference) - [Scopes](https://airtable.com/developers/web/api/scopes) - [Personal access tokens](https://airtable.com/developers/web/guides/personal-access-tokens)