Description
Airtable Webhook for n8n





n8n community node that triggers workflows instantly when Airtable records change — using real Airtable webhooks, not polling.
Originally forked from @vwork-digital/n8n-nodes-instant-airtable-trigger, fully rewritten by D1DX.
How It Works
1. Activate a workflow with this trigger — registers an Airtable webhook on your base
2. Airtable sends a notification ping to n8n on every matching change
3. The node fetches the webhook payloads with cursor-based pagination
4. Payloads are parsed into flat per-record items with field names resolved
5. Deactivate the workflow — webhook is automatically deleted
Important: Airtable webhooks expire every 7 days. Use a separate scheduled workflow to refresh them.
Installation
1. Go to Settings > Community Nodes in your n8n instance
2. Click Install a community node
3. Enter @d1dx/n8n-nodes-airtable
4. Click Install
Or via CLI:
cd ~/.n8n
npm install @d1dx/n8n-nodes-airtable
Restart n8n
Configuration
All field names map directly to the Airtable Webhooks API specification.
Core Fields (always visible)
| Field | Airtable API | Description |
|——-|————-|————-|
| Base | — | Dropdown of all bases (via meta API) |
| Table | — | Dropdown of tables in selected base |
| View | recordChangeScope | Scope to a specific view. “Add” = entered view, “Remove” = left view. Form/List views not supported. Leave empty for entire table. |
| Change Types | changeTypes | Add / Update / Remove. Leave empty = all. Sent server-side to Airtable. |
Shown when “Update” is selected
| Field | Airtable API | Description |
|——-|————-|————-|
| Fields to Watch | watchDataInFieldIds | Only trigger on changes to these fields. Leave empty = all fields. Warning: webhook permanently stops if a listed field is deleted. |
| Include Previous Values | includePreviousCellValues | Include the previous value alongside current for changed fields. |
Output Options (always visible)
| Field | Airtable API | Description |
|——-|————-|————-|
| Fields to Include in Output | includeCellValuesInFieldIds | Always include these field values, even if unchanged. Select “All fields” to send "all" to API. Safe if a listed field is deleted. |
| Use Field Names | — | Resolve field IDs (e.g. fldABC123) to human names (e.g. Status) in output. |
Advanced Options
| Field | Airtable API | Description |
|——-|————-|————-|
| Data Types | dataTypes | tableData (default), tableFields, tableMetadata. Can combine multiple. |
| From Sources | fromSources | Filter by source: client, publicApi, automation, formSubmission, formPageSubmission, sync, system, anonymousUser, unknown. Empty = all. |
| Form Submission View ID | sourceOptions.formSubmission.viewId | Filter form submissions to a specific form view. Only relevant when “Form Submission” is in From Sources. |
| Form Page Submission Page ID | sourceOptions.formPageSubmission.pageId | Filter interface page submissions to a specific page. Only relevant when “Form Page Submission” is in From Sources. |
| Watch Field Schema Changes | watchSchemasOfFieldIds | Only trigger on schema changes for these fields. Requires tableFields data type. Warning: webhook stops if field is deleted. |
| Include Previous Field Definitions | includePreviousFieldDefinitions | Include previous field name/type in field change payloads. Requires tableFields data type. |
Credentials
You need an Airtable Personal Access Token (PAT):
1. Go to airtable.com/create/tokens
2. Create a token with these scopes:
– webhook:manage — register and delete webhooks
– data.records:read — read webhook payloads
– schema.bases:read — populate base/table/view/field dropdowns
3. Grant access to the bases you want to watch
4. In n8n, create an “Airtable API” credential and paste the token
Output Format
One item per event. All items include eventType, recordId, tableId, source, changedBy, timestamp.
Record events (tableData)
Created:
{
"eventType": "created",
"recordId": "recXXXXXXXXXXXXXX",
"tableId": "tblXXXXXXXXXXXXXX",
"viewId": "viwXXXXXXXXXXXXXX",
"createdTime": "2026-04-05T12:00:00.000Z",
"fields": { "Status": "New", "Name": "Example" },
"source": "client",
"changedBy": { "userId": "usrXXXX", "userName": "John", "userEmail": "john@example.com" },
"timestamp": "2026-04-05T12:00:00.000Z"
}
Updated:
{
"eventType": "updated",
"recordId": "recXXXXXXXXXXXXXX",
"tableId": "tblXXXXXXXXXXXXXX",
"changedFields": ["Status"],
"current": { "Status": "Done" },
"previous": { "Status": "Active" },
"unchanged": { "Name": "Example" },
"source": "client",
"changedBy": { "userId": "usrXXXX", "userName": "John", "userEmail": "john@example.com" },
"timestamp": "2026-04-05T12:00:00.000Z"
}
Deleted:
{
"eventType": "deleted",
"recordId": "recXXXXXXXXXXXXXX",
"tableId": "tblXXXXXXXXXXXXXX",
"source": "client",
"timestamp": "2026-04-05T12:00:00.000Z"
}
Field schema events (tableFields)
| eventType | Key fields |
|———–|———–|
| fieldCreated | fieldId, name, type |
| fieldChanged | fieldId, current, previous |
| fieldDeleted | fieldId |
Table metadata events (tableMetadata)
| eventType | Key fields |
|———–|———–|
| metadataChanged | current (name, description), previous |
Error events
| eventType | Key fields |
|———–|———–|
| error | code: INVALIDFILTERS, INVALIDHOOK, or INTERNAL_ERROR |
Gotchas
- View-scoped payloads have different structure. When
recordChangeScopeis a view, Airtable nests records insidechangedViewsByIdinstead of directly on the table. The node handles this transparently. - 10 webhooks per base. Each active workflow uses one webhook. Plan accordingly.
- Webhooks expire in 7 days. Refresh them or they stop silently.
- Field deletion kills the webhook. If a field in
watchDataInFieldIdsorwatchSchemasOfFieldIdsis deleted, the webhook enters a permanent error state. Must deactivate and reactivate. Exception:includeCellValuesInFieldIdsis safe — deleted fields are silently ignored. - Creator permissions required. The PAT owner must have Creator access to register webhooks.
- Community node updates require n8n restart. n8n loads node code at startup, not dynamically.
- Cursor change reverted. Restored
cursor: cursorForNextPayload - 1(the v2.3.2 form). Empirical probe of Airtable’s/bases/{base}/webhooks/{id}/payloadsendpoint: whencursorForNextPayload = N,?cursor=Nreturns 0 payloads;?cursor=N-1returns the latest payload. Airtable’scursorForNextPayloadis the cursor of the next-to-be-generated payload, not the next-to-fetch — the v2.3.3 changelog claim was wrong. The- 1fetches the most recent payload as intended. - Bug 2 (delete-error logging) and bug 3 (create-side dedup) from 2.3.3 are kept. Both verified working live during the 2.3.3 deploy cycle (cleaned 2 stale webhooks).
- Known limitation (deferred to 2.4.0): the trigger fetches only the latest payload per fire. If multiple events land between fires, only the most recent is emitted. Source-of-truth move to staticData
lastCursorplus pagination viamightHaveMoreis the planned fix. - Cursor re-read “fix” was wrong. Changed
cursor: cursorForNextPayload - 1→cursor: cursorForNextPayload. Empirical re-test (post-publish) showed N points to the next-to-be-generated payload, so?cursor=Nreturns 0 rows. Reverted in 2.3.4. The original- 1was correct. delete()no longer fails silently. Previously caught any DELETE error and returnedfalsewith no log line. n8n then proceeded tocreate()and the old webhook stayed live in Airtable alongside the new one — duplicate webhooks accumulated across save cycles. Now logs the error message viaconsole.errorso the failure is diagnosable. Return value stillfalseso the n8n deactivate flow continues to work. (Kept in 2.3.4.)create()is now idempotent. Before POSTing a new webhook, GETs the base’s existing webhooks, finds any whosenotificationUrlmatches this n8n endpoint, and DELETEs them first. Stops the duplicate-accumulation pattern at the source. Pre-create dedup also self-heals from situations where priordelete()calls failed silently. (Kept in 2.3.4.)- Respect Data Types selection when emitting events — schema/metadata events were previously emitted unconditionally.
- Airtable Webhooks API
- Airtable Create Webhook
- Airtable Webhook Payloads
- n8n Community Nodes
Changelog
2.3.4 — 2026-05-09
Hotfix — reverts the cursor change shipped in 2.3.3. Anyone on 2.3.3 should upgrade immediately: that release silently dropped every event from every Airtable trigger.
2.3.3 — 2026-05-09 (broken — do not use)
Three trigger-node bug fixes uncovered during a flood-rate investigation on a long-running production workflow. Bug-1 fix introduced a regression that silently drops every webhook event; reverted in 2.3.4 above.
2.3.2 — 2026-04-30
Maintainer notes
This package ships pre-built dist/ files. There is no .ts source committed to this repo. Edit dist/nodes/AirtableTrigger/AirtableTrigger.node.js directly and bump the version in package.json. The prepublishOnly script runs node --check against the dist files as a syntax guard before npm publish.
Do not run npm run build — tsc has no source to compile and would clobber the dist files with empty output.
CI: pushing a v* tag triggers .github/workflows/publish.yml, which checks out the tag and runs npm publish with the NPM_TOKEN secret.
Credits
Originally created by Jacob Vendramin at vwork Digital as @vwork-digital/n8n-nodes-instant-airtable-trigger (MIT license). Forked and rewritten by D1DX.
License
MIT — see LICENSE.md