{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreigllfcha32gpr3ejwgdcmyjhqtdoytgcc5az4l652hcnlv4256qne",
"uri": "at://did:plc:25rdn5elo5izoxrmtis34zuk/app.bsky.feed.post/3mpe4p5v2plq2"
},
"coverImage": {
"$type": "blob",
"ref": {
"$link": "bafkreidzsxi22dvo3yvdmhoifbajjzuq2ncccdmip2bb2muanmopcpfe5y"
},
"mimeType": "image/webp",
"size": 70820
},
"path": "/pirateprentice/n8n-airtable-node-read-create-update-and-delete-records-free-json-5462",
"publishedAt": "2026-06-28T13:30:48.000Z",
"site": "https://dev.to",
"tags": [
"automation",
"database",
"tooling",
"tutorial",
"n8n Workflow Starter Pack ($29)"
],
"textContent": "# n8n Airtable Node: Read, Create, Update, and Delete Records (Free JSON)\n\nAirtable is one of the most popular no-code databases — part spreadsheet, part database, fully visual. If your team lives in Airtable, the n8n Airtable node lets you automate every record operation without writing a line of Airtable scripting.\n\nThis guide covers setup, every operation with examples, common gotchas, and a free workflow JSON you can import directly.\n\n## Prerequisites\n\n * n8n instance (cloud or self-hosted)\n * An Airtable account with at least one base\n * An Airtable personal access token (API key is deprecated as of Feb 2024)\n\n\n\n## Step 1: Create an Airtable Personal Access Token\n\n 1. Go to **airtable.com/account** → **Developer Hub** → **Personal access tokens**\n 2. Click **+ Create new token**\n 3. Name it (e.g., `n8n-integration`)\n 4. Add **scopes** : at minimum `data.records:read`, `data.records:write`, `schema.bases:read`\n 5. Under **Access** , select the specific bases you want n8n to reach (or all bases)\n 6. Copy the token — it only shows once\n\n\n\n> **Why scopes matter:** Airtable's new token system is scope-based. If you forget `data.records:write` and try to create a record, you'll get a 403 with no helpful error message. Match your scopes to the operations you plan to use.\n\n## Step 2: Add the Credential in n8n\n\n 1. In n8n, go to **Credentials** → **New** → search **Airtable**\n 2. Select **Airtable Personal Access Token**\n 3. Paste your token\n 4. Click **Save** — n8n verifies the connection immediately\n\n\n\n## Step 3: Add the Airtable Node to Your Workflow\n\n 1. Click **+** in the workflow canvas\n 2. Search for **Airtable**\n 3. Select the operation you need (see below)\n\n\n\n## All Airtable Node Operations\n\n### Search Records\n\nSearches your table using a filter formula and returns matching records.\n\n**Key settings:**\n\n * **Base** : select your Airtable base\n * **Table** : select the table\n * **Filter By Formula** : Airtable formula syntax, e.g., `{Status} = \"Active\"` or `IS_BEFORE({Due Date}, TODAY())`\n * **Return All** : toggle on to get every matching record; otherwise returns up to 100\n\n\n\n**Output:** Array of record objects, each with `id` and `fields`.\n\n\n\n // Example output item\n {\n \"id\": \"recABC123\",\n \"fields\": {\n \"Name\": \"Acme Corp\",\n \"Status\": \"Active\",\n \"Revenue\": 50000\n }\n }\n\n\n**Common use case:** Pull all \"Active\" leads every morning and send a Slack summary.\n\n### List Records\n\nReturns all records in a table (with optional sort and filter).\n\n**Difference from Search:** List is for bulk retrieval; Search is when you have a specific formula condition. In practice they overlap — use whichever feels clearer for your use case.\n\n**Key settings:**\n\n * **Sort** : add sort fields and direction (ascending/descending)\n * **Fields** : list only the fields you need (reduces payload size)\n * **View** : restrict to a specific Airtable view's records\n\n\n\n### Get Record\n\nFetches a single record by its record ID.\n\n**Key settings:**\n\n * **Record ID** : the `recXXXXXXXXXX` string (usually passed from a prior Search/List node)\n\n\n\n**Use case:** After a webhook fires with a record ID, fetch the full record details before processing.\n\n### Create Record\n\nAdds one new record to a table.\n\n**Key settings:**\n\n * **Fields** : map n8n expressions to Airtable field names\n\n\n\n\n Name → {{ $json.name }}\n Email → {{ $json.email }}\n Source → \"n8n webhook\"\n Created Date → {{ $now.toISO() }}\n\n\n> **Field name must match exactly.** Airtable field names are case-sensitive. \"email\" and \"Email\" are different fields. If a field doesn't exist in the table, the node silently ignores it — no error, just missing data.\n\n### Update Record\n\nUpdates fields on an existing record.\n\n**Key settings:**\n\n * **Record ID** : the ID of the record to update (from a prior node)\n * **Fields** : only the fields you want to change (unspecified fields are left unchanged)\n\n\n\n**Common pattern:**\n\n\n\n [Trigger] → [Search Records: find by email] → [Update Record: set Status = \"Replied\"]\n\n\n### Upsert Record (Create or Update)\n\nChecks if a record matching your field value exists; updates it if found, creates it if not.\n\n**Key settings:**\n\n * **Fields to Match On** : the field(s) used to find an existing record (e.g., \"Email\")\n * **Fields** : the values to set/update\n\n\n\nThis is the most powerful operation for sync workflows — it keeps Airtable in sync with an external source without creating duplicates.\n\n### Delete Record\n\nPermanently deletes a record by ID. **Irreversible.**\n\n**Key settings:**\n\n * **Record ID** : pass from a Search/List node\n\n\n\n## Operation Quick Reference\n\nOperation | When to use\n---|---\nSearch Records | Filter by formula — get records matching a condition\nList Records | Get all records, optionally sorted/filtered by view\nGet Record | Fetch one record by known ID\nCreate Record | Add a new row\nUpdate Record | Change fields on an existing row (ID required)\nUpsert Record | Sync external data — create if new, update if exists\nDelete Record | Remove a row permanently\n\n## Common Gotchas\n\n### 1. Old API key vs. Personal Access Token\n\nAirtable deprecated API keys in February 2024. If you see a 401 error, you're using the old credential type. Delete the old credential in n8n and create a new **Airtable Personal Access Token** credential.\n\n### 2. Formula syntax in Filter By Formula\n\nAirtable formulas use their own syntax. Common mistakes:\n\n * Field names with spaces need curly braces: `{First Name}` not `First Name`\n * String values need quotes: `{Status} = \"Active\"` not `{Status} = Active`\n * Dates: use `IS_BEFORE()`, `IS_AFTER()`, `TODAY()` — not JavaScript date methods\n\n\n\n### 3. Rate limits\n\nAirtable's API rate limit is **5 requests per second per base**. If you're looping over hundreds of records and creating/updating each one individually, you'll hit 429 errors. Solutions:\n\n * Add a **Wait** node (1 second) between batches\n * Use a **Split in Batches** node with a small batch size\n * Use Upsert to combine create + update into one call where possible\n\n\n\n### 4. Field type mismatches\n\nAirtable is strict about field types. You cannot write a string to a Number field or an array to a Single Line Text field. If your data comes from an external source, validate/convert types in a **Code** or **Set** node before the Airtable node.\n\n### 5. Linked Record fields\n\nLinked Record fields in Airtable store arrays of record IDs, not display values. To write to a linked field:\n\n\n\n { \"Project\": [\"recXXXX\", \"recYYYY\"] }\n\n\nTo read the display value of a linked record, you need a second Airtable Get Record call on the linked table.\n\n## Free Workflow: Webhook → Airtable Lead Capture\n\nThis workflow receives a webhook (e.g., from a contact form) and upserts the lead into an Airtable CRM base — no duplicates, no manual data entry.\n\n\n\n {\n \"name\": \"Webhook → Airtable Lead Capture\",\n \"nodes\": [\n {\n \"parameters\": {\n \"httpMethod\": \"POST\",\n \"path\": \"new-lead\",\n \"responseMode\": \"responseNode\"\n },\n \"id\": \"a1b2c3d4-0001-0001-0001-000000000001\",\n \"name\": \"Webhook\",\n \"type\": \"n8n-nodes-base.webhook\",\n \"typeVersion\": 2,\n \"position\": [250, 300]\n },\n {\n \"parameters\": {\n \"operation\": \"upsert\",\n \"base\": { \"__rl\": true, \"value\": \"YOUR_BASE_ID\", \"mode\": \"id\" },\n \"table\": { \"__rl\": true, \"value\": \"YOUR_TABLE_ID\", \"mode\": \"id\" },\n \"columns\": {\n \"mappingMode\": \"defineBelow\",\n \"value\": {\n \"Email\": \"={{ $json.body.email }}\",\n \"Name\": \"={{ $json.body.name }}\",\n \"Company\": \"={{ $json.body.company }}\",\n \"Source\": \"n8n webhook\",\n \"Last Seen\": \"={{ $now.toISO() }}\"\n }\n },\n \"matchingColumns\": [\"Email\"]\n },\n \"id\": \"a1b2c3d4-0002-0002-0002-000000000002\",\n \"name\": \"Airtable\",\n \"type\": \"n8n-nodes-base.airtable\",\n \"typeVersion\": 2,\n \"position\": [450, 300]\n },\n {\n \"parameters\": {\n \"respondWith\": \"json\",\n \"responseBody\": \"={ \\\"ok\\\": true }\"\n },\n \"id\": \"a1b2c3d4-0003-0003-0003-000000000003\",\n \"name\": \"Respond to Webhook\",\n \"type\": \"n8n-nodes-base.respondToWebhook\",\n \"typeVersion\": 1,\n \"position\": [650, 300]\n }\n ],\n \"connections\": {\n \"Webhook\": { \"main\": [[{ \"node\": \"Airtable\", \"type\": \"main\", \"index\": 0 }]] },\n \"Airtable\": { \"main\": [[{ \"node\": \"Respond to Webhook\", \"type\": \"main\", \"index\": 0 }]] }\n }\n }\n\n\n**To use this:**\n\n 1. Replace `YOUR_BASE_ID` and `YOUR_TABLE_ID` with your actual IDs (find them in your Airtable URL: `airtable.com/YOUR_BASE_ID/YOUR_TABLE_ID`)\n 2. Add your Airtable credential to the node\n 3. Adjust field names to match your table\n\n\n\n## What's in the n8n Workflow Starter Pack?\n\nThe free JSON above handles the basics. The **n8n Workflow Starter Pack ($29)** includes:\n\n * **15 production-ready workflows** (Airtable, Notion, Slack, Gmail, Stripe, OpenAI, and more)\n * Complete setup instructions for each\n * Error handling and retry logic built in\n * Airtable-specific workflows: lead capture, CRM sync, inventory alerts, form-to-base\n\n\n\nOne purchase, instant download, no subscription.\n\n## Summary\n\nThe n8n Airtable node covers the full CRUD surface of your bases. The main things to get right:\n\n 1. Use a **Personal Access Token** (not the deprecated API key)\n 2. Set the right **scopes** on the token\n 3. Match **field names exactly** (case-sensitive)\n 4. Use **Upsert** for sync workflows to avoid duplicates\n 5. Respect the **5 req/sec rate limit** with Wait or batch nodes\n\n\n\nIf you're building automations that touch Airtable regularly, this node will become one of your most-used.\n\n_What Airtable automation are you trying to build? Drop it in the comments — happy to help with the formula or field mapping._",
"title": "n8n Airtable Node: Read, Create, Update, and Delete Records (Free JSON)"
}