Airtable
Read and write records in Airtable bases with webhook payload polling.
Authentication
| Type | Default | Details |
|---|---|---|
api_key | ✅ | Personal Access Token (pat_...) |
oauth_2 | Airtable OAuth with PKCE |
Airtable OAuth requires PKCE and uses scopes:
data.records:readdata.records:writeschema.bases:read
Endpoints
| Path | Risk | Description |
|---|---|---|
records.list | read | List records in a table. |
records.get | read | Get a single record. |
records.create | write | Create up to 10 records in one call. |
records.update | write | Patch up to 10 records (partial fields). |
records.delete | destructive | Delete up to 10 records. |
webhooks.listPayloads | read | Poll the buffered payloads for a webhook subscription. |
records.list
List records in a table with filtering, sorting, and pagination.
Input:
| Field | Type | Required | Description |
|---|---|---|---|
baseId | string | ✅ | Base ID |
tableIdOrName | string | ✅ | Table ID or name |
view | string | View name to filter by | |
fields | string[] | Only return these field names | |
filterByFormula | string | Airtable formula filter | |
pageSize | number | Max records per page (max 100) | |
offset | string | Pagination offset | |
sort | array | Sort configs: { field: string; direction?: "asc" | "desc" } |
Output: { records: AirtableRecord[]; offset?: string }
records.get
Get a single record by ID.
Input:
| Field | Type | Required | Description |
|---|---|---|---|
baseId | string | ✅ | Base ID |
tableIdOrName | string | ✅ | Table ID or name |
recordId | string | ✅ | Record ID |
Output: AirtableRecord
records.create
Create up to 10 records in one call.
Input:
| Field | Type | Required | Description |
|---|---|---|---|
baseId | string | ✅ | Base ID |
tableIdOrName | string | ✅ | Table ID or name |
records | array | ✅ | Array of { fields: Record<string, unknown> } |
typecast | boolean | Auto-convert types |
Output: { records: AirtableRecord[] }
records.update
Update up to 10 records with partial fields.
Input:
| Field | Type | Required | Description |
|---|---|---|---|
baseId | string | ✅ | Base ID |
tableIdOrName | string | ✅ | Table ID or name |
records | array | ✅ | Array of { id: string; fields: Record<string, unknown> } |
typecast | boolean | Auto-convert types |
Output: { records: AirtableRecord[] }
records.delete
Delete up to 10 records.
Input:
| Field | Type | Required | Description |
|---|---|---|---|
baseId | string | ✅ | Base ID |
tableIdOrName | string | ✅ | Table ID or name |
records | string[] | ✅ | Array of record IDs to delete |
Output: { records: Array<{ id: string; deleted: boolean }> }
webhooks.listPayloads
Poll buffered webhook payloads for a subscription. Airtable webhooks require polling — push events only notify "something changed."
Input:
| Field | Type | Required | Description |
|---|---|---|---|
baseId | string | ✅ | Base ID |
webhookId | string | ✅ | Webhook ID |
cursor | number | Pagination cursor | |
limit | number | Max payloads |
Output: { payloads: unknown[]; cursor: number; mightHaveMore: boolean; payloadFormat: "v0" }
Usage
import { createFabric } from "@fabricorg/integrations";
import { airtable } from "@fabricorg/integrations/plugins";
const fabric = createFabric({
plugins: [airtable({ apiKey: process.env.AIRTABLE_PAT })],
});
// List records
const { records } = await fabric.airtable.api.records.list({
baseId: "appABCDEF123456",
tableIdOrName: "Tasks",
filterByFormula: '{Status} = "In Progress"',
sort: [{ field: "Due Date", direction: "asc" }],
});
// Create records
const { records: created } = await fabric.airtable.api.records.create({
baseId: "appABCDEF123456",
tableIdOrName: "Tasks",
records: [
{ fields: { Name: "New Task", Status: "Todo", Priority: "High" } },
],
});Webhooks
Airtable's webhook contract requires polling. Push events notify "something changed in baseId," then you poll for payloads via webhooks.listPayloads. The portal's webhook bridge handles the poll loop.
Direct webhook handlers are not declared on this plugin.
Types
interface AirtableRecord<Fields = Record<string, unknown>> {
id: string;
fields: Fields;
createdTime: string;
}