<!-- BusyBot node reference — https://busybot.net/tools/airtable/ -->

> Node: Airtable (`airtable`) · Action (binary) · v1
> Category: Data & Storage · Credentials: Airtable API (`airtableApi`)
> Updated: 2026-08-16

# Airtable

> Read, create, update, delete, and search Airtable records with attachment download

## Overview

The Airtable tool provides full CRUD operations for Airtable records via the Airtable REST API v0. Supports two resources: (1) Record -- create, delete, get, search (list/filter), update, and upsert. Record get and search operations can optionally download attachment fields as binary data with naming pattern {fieldName}_{index}. (2) Base -- list all accessible bases with permission filtering, and retrieve the full schema (tables, fields, views) of a base. Uses Bearer token authentication. Supports pagination for search (offset-based, 100 records/page), auto-batching for update/upsert (max 10 records/PATCH), and upsert fallback logic for 422 errors and multi-match scenarios.

**Category:** Data & Storage  
**Tool Name:** `airtable`  
**Version:** 1

**Appearance:** Icon: `si-airtable` | Color: `#18BFFF`

## Node Type

**Action (Binary)** — handles file/binary data operations

## Input / Output

| Direction | Port(s) |
|-----------|--------|
| Input | `Input` |
| Output | `Output`, `Error` |

## Credentials

This tool requires **Airtable API** credentials.
See the [Credentials Guide](https://busybot.net/credentials/airtable-api/) for setup instructions.

### Resources

| Resource | Value |
|----------|-------|
| Base | `base` |
| Record | `record` |

### Operations

Operations for the `record` resource:

| Operation | Value | Description |
|-----------|-------|-------------|
| Create | `create` | Create a new record in a table |
| Delete | `delete` | Delete a record by ID |
| Get | `get` | Retrieve a single record by ID |
| Search | `search` | Search for records or list all |
| Update | `update` | Update an existing record |
| Upsert | `upsert` | Create or update a record |

Operations for the `base` resource:

| Operation | Value | Description |
|-----------|-------|-------------|
| Get Many | `getMany` | List all accessible bases |
| Get Schema | `getSchema` | Get the schema of a base |

### Parameters

#### Record: Create

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Base ID | `string` | Yes | — | The Airtable Base ID. Find it in the URL: https://airtable.com/{baseId}/... |
| Table ID | `string` | Yes | — | The Table ID or name (URI-encoded if name contains special characters). |
| Fields (JSON) | `json` | Yes | `{}` | Key-value pairs of column name to value. Example: {"Name": "John", "Email": "john@example.com"}. Set to "autoMap" to auto-map all input item JSON fields. |
| Typecast | `boolean` | No | `false` | Whether the Airtable API should attempt mapping of string values for linked records and select options. |
| Ignore Fields | `string` | No | — | Comma-separated list of fields to ignore when auto-mapping input data. |

#### Record: Delete

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Base ID | `string` | Yes | — | The Airtable Base ID. Find it in the URL: https://airtable.com/{baseId}/... |
| Table ID | `string` | Yes | — | The Table ID or name (URI-encoded if name contains special characters). |
| Record ID | `string` | Yes | — | The ID of the record to delete. |

#### Record: Get

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Base ID | `string` | Yes | — | The Airtable Base ID. Find it in the URL: https://airtable.com/{baseId}/... |
| Table ID | `string` | Yes | — | The Table ID or name (URI-encoded if name contains special characters). |
| Record ID | `string` | Yes | — | The ID of the record to retrieve. |
| Download Attachments | `string` | No | — | Comma-separated names of attachment-type fields to download as binary data. Binary properties are named {fieldName}_{index}. Leave empty to skip attachment download. |

#### Record: Search

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Base ID | `string` | Yes | — | The Airtable Base ID. Find it in the URL: https://airtable.com/{baseId}/... |
| Table ID | `string` | Yes | — | The Table ID or name (URI-encoded if name contains special characters). |
| Filter By Formula | `string` | No | — | Airtable formula to filter records. If empty, all records are returned. See https://support.airtable.com/docs/formula-field-reference |
| Return All | `boolean` | No | `true` | Whether to return all results or only up to a given limit. |
| Limit | `number` | No | `100` | Max number of records to return (max 100). _(shown when Return All is `false`)_ |
| Download Attachments | `string` | No | — | Comma-separated names of attachment-type fields to download as binary data. Binary properties are named {fieldName}_{index}. Leave empty to skip attachment download. |
| Output Fields | `string` | No | — | Comma-separated list of field names to include in the output. Leave empty to return all fields. |
| View | `string` | No | — | View ID or name to filter by. Only records visible in this view will be returned. |
| Sort | `json` | No | `[]` | Sort rules as JSON array: [{"field": "Name", "direction": "asc"}, {"field": "Date", "direction": "desc"}]. direction can be "asc" or "desc". |

#### Record: Update

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Base ID | `string` | Yes | — | The Airtable Base ID. Find it in the URL: https://airtable.com/{baseId}/... |
| Table ID | `string` | Yes | — | The Table ID or name (URI-encoded if name contains special characters). |
| Fields (JSON) | `json` | Yes | `{}` | Key-value pairs of column name to value to update. Include matching column values. Set to "autoMap" to auto-map all input item JSON fields. |
| Matching Columns | `string` | Yes | `id` | Comma-separated list of columns to match on. Use "id" to match by Airtable record ID. For upsert, these columns identify whether to create or update. |
| Typecast | `boolean` | No | `false` | Whether the Airtable API should attempt mapping of string values for linked records and select options. |
| Ignore Fields | `string` | No | — | Comma-separated list of fields to ignore when auto-mapping input data. |
| Update All Matches | `boolean` | No | `false` | Whether to update all records matching the matching columns. If false, only the first match is updated. |

#### Record: Upsert

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Base ID | `string` | Yes | — | The Airtable Base ID. Find it in the URL: https://airtable.com/{baseId}/... |
| Table ID | `string` | Yes | — | The Table ID or name (URI-encoded if name contains special characters). |
| Fields (JSON) | `json` | Yes | `{}` | Key-value pairs of column name to value to update. Include matching column values. Set to "autoMap" to auto-map all input item JSON fields. |
| Matching Columns | `string` | Yes | `id` | Comma-separated list of columns to match on. Use "id" to match by Airtable record ID. For upsert, these columns identify whether to create or update. |
| Typecast | `boolean` | No | `false` | Whether the Airtable API should attempt mapping of string values for linked records and select options. |
| Ignore Fields | `string` | No | — | Comma-separated list of fields to ignore when auto-mapping input data. |
| Update All Matches | `boolean` | No | `false` | Whether to update all records matching the matching columns. If false, only the first match is updated. |

#### Base: Get Many

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Return All | `boolean` | No | `true` | Whether to return all bases or only up to a given limit. |
| Limit | `number` | No | `100` | Max number of bases to return. _(shown when Return All is `false`)_ |
| Permission Level | `multiOptions` | No | `[]` | Filter returned bases by permission level. |
| | | | | Options: `comment`, `create`, `edit`, `none`, `read` |

#### Base: Get Schema

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Base ID | `string` | Yes | — | The Airtable Base ID to retrieve the schema from. |

#### All Operations

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| Max Concurrency | `number` | No | `5` | Maximum number of items to process concurrently. Airtable rate limits to 5 requests/second per base, so keep this low. |

## Output Data

Results are merged onto the input item's JSON, so the properties you started with remain available. Airtable's `fields` object is flattened: every column becomes a top-level property of the item, alongside the record's `id` and `createdTime`. Binary data on the input item is forwarded.

| Operation | Output |
|-----------|--------|
| `create` | One item per input item, carrying the created record — its `id` and every column. |
| `get` | One item per input item, carrying the requested record. |
| `delete` | One item per input item, carrying Airtable's delete confirmation for that record ID. |
| `search` | **Fans out** — one output item per matching record. |
| `update` | One item per input item. A single match is flattened onto the item; when several records were updated they arrive as an array on `updatedRecords`. |
| `upsert` | One item per input item. A single match is flattened onto the item; when several records were written they arrive as an array on `upsertedRecords`. |
| `getMany` | **Fans out** — one output item per accessible base, carrying that base's metadata including its `permissionLevel`. |
| `getSchema` | **Fans out** — one output item per table in the base, carrying that table's definition (fields and views). |

Operations that fan out emit a single item carrying `_noResults: true` when nothing matched, so the branch never goes silent. Check for it before treating the item as a record:

```json
{
  "_noResults": true
}
```

**Attachments.** With **Download Attachments** set on `get` or `search`, every attachment in the named fields is downloaded and attached to the output item as binary. Each binary property is named `{fieldName}_{index}` — the first file in a `Documents` field becomes `Documents_0`, the second `Documents_1`. The record's JSON still carries Airtable's own attachment metadata, so you can read the original file name from there and the bytes from the binary property.

Reference results downstream by expression, e.g. `{{ $json.id }}` or `{{ $json.Email }}`.

## Usage Examples

- Search all records in an Airtable table and download attachment fields
- Create a new record in Airtable with typecast enabled
- Update an Airtable record matched by email column
- Upsert records to avoid duplicates using a unique column
- List all accessible Airtable bases
- Get the schema (tables and fields) of an Airtable base

## Example Configuration

Create a record:

```json
{
  "type": "airtable",
  "parameters": {
    "resource": "record",
    "operation": "create",
    "baseId": "appXXXXXXXXXXXXXX",
    "tableId": "tblYYYYYYYYYYYYYY",
    "fields": {
      "Name": "{{ $json.name }}",
      "Email": "{{ $json.email }}",
      "Age": 30
    },
    "typecast": true
  }
}
```

Map every property of the incoming item to a column, skipping the ones Airtable should not see:

```json
{
  "type": "airtable",
  "parameters": {
    "resource": "record",
    "operation": "create",
    "baseId": "appXXXXXXXXXXXXXX",
    "tableId": "tblYYYYYYYYYYYYYY",
    "fields": "autoMap",
    "ignoreFields": "internal_id,temp_field",
    "typecast": true
  }
}
```

Search with a formula, sorted, returning only the columns you need:

```json
{
  "type": "airtable",
  "parameters": {
    "resource": "record",
    "operation": "search",
    "baseId": "appXXXXXXXXXXXXXX",
    "tableId": "tblYYYYYYYYYYYYYY",
    "filterByFormula": "AND({Status} = 'Active', {Age} > 25)",
    "returnAll": false,
    "limit": 50,
    "sort": [
      { "field": "Name", "direction": "asc" },
      { "field": "Created", "direction": "desc" }
    ],
    "outputFields": "Name,Email,Status,Age"
  }
}
```

Search a saved view and pull every attachment down as binary:

```json
{
  "type": "airtable",
  "parameters": {
    "resource": "record",
    "operation": "search",
    "baseId": "appXXXXXXXXXXXXXX",
    "tableId": "tblYYYYYYYYYYYYYY",
    "view": "viwActiveCustomers",
    "filterByFormula": "AND({Last Contact} > DATEADD(TODAY(), -30, 'days'), {Priority} != '')",
    "returnAll": true,
    "sort": [{ "field": "Priority", "direction": "desc" }],
    "downloadFields": "Contract,Invoice"
  }
}
```

Get one record and download its attachments:

```json
{
  "type": "airtable",
  "parameters": {
    "resource": "record",
    "operation": "get",
    "baseId": "appXXXXXXXXXXXXXX",
    "tableId": "tblYYYYYYYYYYYYYY",
    "id": "{{ $json.recordId }}",
    "downloadFields": "Profile Photo,Documents"
  }
}
```

Update the record whose Email column matches:

```json
{
  "type": "airtable",
  "parameters": {
    "resource": "record",
    "operation": "update",
    "baseId": "appXXXXXXXXXXXXXX",
    "tableId": "tblYYYYYYYYYYYYYY",
    "fields": {
      "Email": "{{ $json.email }}",
      "Status": "Updated"
    },
    "matchingColumns": "Email",
    "updateAllMatches": false,
    "typecast": true
  }
}
```

Upsert on a unique column so repeat runs do not create duplicates:

```json
{
  "type": "airtable",
  "parameters": {
    "resource": "record",
    "operation": "upsert",
    "baseId": "appXXXXXXXXXXXXXX",
    "tableId": "tblYYYYYYYYYYYYYY",
    "fields": {
      "Email": "{{ $json.email }}",
      "Name": "{{ $json.name }}",
      "Status": "Active"
    },
    "matchingColumns": "Email",
    "typecast": true
  }
}
```

Delete a record by ID:

```json
{
  "type": "airtable",
  "parameters": {
    "resource": "record",
    "operation": "delete",
    "baseId": "appXXXXXXXXXXXXXX",
    "tableId": "tblYYYYYYYYYYYYYY",
    "id": "{{ $json.recordId }}"
  }
}
```

List the bases you can edit or create in:

```json
{
  "type": "airtable",
  "parameters": {
    "resource": "base",
    "operation": "getMany",
    "returnAll": true,
    "permissionLevel": ["edit", "create"]
  }
}
```

Read a base's schema, one item per table:

```json
{
  "type": "airtable",
  "parameters": {
    "resource": "base",
    "operation": "getSchema",
    "baseId": "appXXXXXXXXXXXXXX"
  }
}
```

### Error Handling

| Mode | Behavior |
|------|----------|
| **stop** | Halts workflow on first error |
| **continue** | Skips failed items, passes successful ones through |
| **errorPort** | Routes failed items to Error output port |

## Tips

Manage Airtable records (CRUD, search, upsert) and download attachment fields as binary data. Also list bases and retrieve base schemas.