This workflow corresponds to n8n.io template #5750 — we link there as the canonical source.
This workflow follows the Airtable → Execute Workflow Trigger recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"meta": {
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "1305d4ee-3227-4adf-99a1-307da4fdef53",
"name": "Execute Workflow Trigger",
"type": "n8n-nodes-base.executeWorkflowTrigger",
"position": [
1340,
320
],
"parameters": {},
"typeVersion": 1
},
{
"id": "300a89e6-ff90-4076-8d93-6189c7669829",
"name": "Inputs",
"type": "n8n-nodes-base.set",
"position": [
1560,
320
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "e202e9a6-e01a-4f3b-b48c-ca8227f05176",
"name": "base_id",
"type": "string",
"value": "={{ $json.base_id }}"
},
{
"id": "0426f50e-8eb6-482b-88fa-0b10c6d31cc0",
"name": "table_id",
"type": "string",
"value": "={{ $json.table_id }}"
},
{
"id": "a6cffb5c-a73d-49e2-87b3-87e4df3bd9b0",
"name": "record_id",
"type": "string",
"value": "={{ $json.record_id }}"
},
{
"id": "6fce3472-be79-4cf7-a5ee-0d7b548ca7e5",
"name": "level_3",
"type": "array",
"value": "={{ $json.level_3 }}"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "f1cdb90e-2cc2-4c0a-a9ee-c1bc5feb240f",
"name": "Split Out Fields",
"type": "n8n-nodes-base.splitOut",
"position": [
2440,
220
],
"parameters": {
"options": {},
"fieldToSplitOut": "fields"
},
"typeVersion": 1
},
{
"id": "894b24e6-3090-46fe-8902-9939595849cd",
"name": "Add Inverse LinkTo Field name",
"type": "n8n-nodes-base.set",
"position": [
2880,
220
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "792af6bc-4537-4959-ab47-7ed38ef369b7",
"name": "inverseFieldName",
"type": "string",
"value": "={{ $('Airtable Schema').all()\n .filter(x => x.json.id == $json.options.linkedTableId)[0].json.fields\n .filter(x => x.id == $json.options.inverseLinkFieldId)[0].name }}"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "44e1d4f9-cd50-4e68-be4c-dd62d5e5eeaa",
"name": "Add origin LinkTo",
"type": "n8n-nodes-base.set",
"position": [
4500,
680
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "f3cb3396-cf4f-42fb-8f62-abc008176ec3",
"name": "originLinkTo",
"type": "string",
"value": "={{ $('Add Inverse LinkTo Field name').item.json.name }}"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "08f499f3-c675-4e4e-865c-397f705a35dd",
"name": "Filter Link To fields",
"type": "n8n-nodes-base.filter",
"position": [
2660,
220
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "cd174792-7f7f-40cb-862e-7ac24ef780ad",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.type }}",
"rightValue": "multipleRecordLinks"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "32cbf163-3114-4fb5-983d-de25f53598af",
"name": "Airtable Schema",
"type": "n8n-nodes-base.airtable",
"position": [
2000,
220
],
"parameters": {
"base": {
"__rl": true,
"mode": "id",
"value": "={{ $('Inputs').item.json.base_id }}"
},
"resource": "base",
"operation": "getSchema"
},
"credentials": {
"airtableTokenApi": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "6d1186d2-96c6-4303-9614-38fa8200a540",
"name": "Airtable - Get Target Record",
"type": "n8n-nodes-base.airtable",
"position": [
1780,
220
],
"parameters": {
"id": "={{ $json.record_id }}",
"base": {
"__rl": true,
"mode": "id",
"value": "={{ $json.base_id }}"
},
"table": {
"__rl": true,
"mode": "id",
"value": "={{ $json.table_id }}"
},
"options": {}
},
"credentials": {
"airtableTokenApi": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "9211e559-f6b3-4086-8a64-37e2218fa221",
"name": "Insert linked records to originRecord & Clean Field Name",
"type": "n8n-nodes-base.code",
"position": [
4740,
680
],
"parameters": {
"jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\n\nlet originRecord = $('Airtable - Get Target Record').first().json\nfor (const item of $input.all()) {\n originRecord[item.json.originLinkTo] = item.json.records.map(x => x.fields);\n //item.json.myNewField = 1;\n}\n\nreturn originRecord;"
},
"typeVersion": 2
},
{
"id": "d928dee8-d050-4ad3-8e54-0dd058900f83",
"name": "Filter Main Table",
"type": "n8n-nodes-base.filter",
"position": [
2220,
220
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "97862298-8455-4516-915e-7983109b48d6",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.id }}",
"rightValue": "={{ $('Inputs').item.json.table_id }}"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "75eb8440-d179-444b-beb1-0e4c41a05293",
"name": "Get Linked records without Link To fields Except for Level 3",
"type": "n8n-nodes-base.httpRequest",
"position": [
3100,
220
],
"parameters": {
"url": "=https://api.airtable.com/v0/{{ $('Inputs').item.json.base_id }}/{{ $json.options.linkedTableId }}/listRecords",
"method": "POST",
"options": {
"batching": {
"batch": {
"batchSize": 4
}
}
},
"sendBody": true,
"sendQuery": true,
"authentication": "predefinedCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "filterByFormula",
"value": "=FIND(RECORD_ID(),\"{{ $('Airtable - Get Target Record').item.json[$json.name].join() }}\")"
},
{
"name": "fields",
"value": "={{ $('Airtable Schema').all().filter(x => x.json.id == $json.options.linkedTableId)[0].json.fields.filter(x => x.type != 'multipleRecordLinks' || $('Inputs').first().json.level_3.includes(x.id)).map(x => x.id)\n}}"
}
]
},
"queryParameters": {
"parameters": [
{}
]
},
"nodeCredentialType": "airtableTokenApi"
},
"credentials": {
"airtableTokenApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "6d908b82-5c3d-4e1c-9c9f-547828c7f462",
"name": "If Has Level 3",
"type": "n8n-nodes-base.if",
"position": [
3540,
-20
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "33590a18-0724-4b8c-923f-05a186ba7a78",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ \n$('Inputs').item.json.level_3\n .some(\n x => $('Airtable Schema').all().filter(x => x.json.id == $('Add Inverse LinkTo Field name').item.json.options.linkedTableId)[0].json.fields.map(x => x.id).includes(x)\n ) \n}}",
"rightValue": "={{ $('Add Inverse LinkTo Field name').item.json.options.linkedTableId }}"
},
{
"id": "4bd93161-a9a9-4bac-a465-8b376bbf728c",
"operator": {
"type": "array",
"operation": "lengthGt",
"rightType": "number"
},
"leftValue": "={{ $json.records }}",
"rightValue": 0
}
]
}
},
"typeVersion": 2.2
},
{
"id": "238b89f0-b68d-4e81-a837-0175348281cc",
"name": "Get L3 Linked records without reverse Link To fields",
"type": "n8n-nodes-base.httpRequest",
"position": [
5140,
-120
],
"parameters": {
"url": "=https://api.airtable.com/v0/{{ $('Inputs').item.json.base_id }}/{{ $json.level_3_table_id }}/listRecords",
"method": "POST",
"options": {
"batching": {
"batch": {
"batchSize": 4
}
}
},
"sendBody": true,
"sendQuery": true,
"authentication": "predefinedCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "filterByFormula",
"value": "=FIND(RECORD_ID(),\"{{ $('Loop Over L2 Records for a given L1 field').item.json.fields[$json.level_2_field_name].join() }}}\")"
},
{
"name": "fields",
"value": "={{ $('Airtable Schema').all().filter(x => x.json.id == $json.level_3_table_id)[0].json.fields.filter(x => x.type != 'multipleRecordLinks' ).map(x => x.id) }}"
}
]
},
"queryParameters": {
"parameters": [
{}
]
},
"nodeCredentialType": "airtableTokenApi"
},
"credentials": {
"airtableTokenApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "b71ff770-0253-4b93-b57b-9ed5a7eb6462",
"name": "Level 2 records",
"type": "n8n-nodes-base.splitOut",
"position": [
4040,
60
],
"parameters": {
"options": {},
"fieldToSplitOut": "records"
},
"typeVersion": 1
},
{
"id": "4d3ad059-ea71-4e76-8ce1-89928b824613",
"name": "Merge",
"type": "n8n-nodes-base.merge",
"position": [
4260,
-40
],
"parameters": {
"mode": "combine",
"options": {},
"combineBy": "combineAll"
},
"typeVersion": 3
},
{
"id": "5e8becd7-9056-424c-bc5c-3cb553b88e78",
"name": "Merge1",
"type": "n8n-nodes-base.merge",
"position": [
4280,
680
],
"parameters": {},
"typeVersion": 3
},
{
"id": "eee4b3a4-dd73-485c-adbc-db64bb22157f",
"name": "Repeat L3 links of current L2 table",
"type": "n8n-nodes-base.set",
"position": [
4040,
-140
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "8f6ae31e-9641-4453-8d28-1a2d1f10a4c7",
"name": "level_3_links",
"type": "array",
"value": "={{ $('Inputs').item.json.level_3.filter(x => $('Airtable Schema').all().filter(x => x.json.id == $('Add Inverse LinkTo Field name').item.json.options.linkedTableId)[0].json.fields.map(x => x.id).includes(x)) }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "8fc621bc-5f9d-4d9c-8c88-12cd7aafca68",
"name": "Aggregate1",
"type": "n8n-nodes-base.aggregate",
"position": [
5580,
-120
],
"parameters": {
"options": {
"mergeLists": false
},
"fieldsToAggregate": {
"fieldToAggregate": [
{
"fieldToAggregate": "level_2_field_name"
},
{
"fieldToAggregate": "level_3_records"
}
]
}
},
"typeVersion": 1
},
{
"id": "c9d8fabd-b9c1-409a-a899-0dc6260a8199",
"name": "Split Out L3 Potential Links",
"type": "n8n-nodes-base.splitOut",
"position": [
4700,
-120
],
"parameters": {
"options": {},
"fieldToSplitOut": "level_3_links"
},
"typeVersion": 1
},
{
"id": "eb8e8c3b-972a-4d6f-878d-cb5d435e0250",
"name": "Prepare HTTP Call",
"type": "n8n-nodes-base.set",
"position": [
4920,
-120
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "e3399e28-b76b-4d7b-ba54-830d4f526f87",
"name": "level_2_table_id",
"type": "string",
"value": "={{ $('Add Inverse LinkTo Field name').item.json.options.linkedTableId }}"
},
{
"id": "42dbca2b-6714-425b-94c2-2dd4f76b3783",
"name": "level_2_field_id",
"type": "string",
"value": "={{ $json.level_3_links }}"
},
{
"id": "915e891e-2e8e-4540-8642-38f44e36008a",
"name": "level_3_table_id",
"type": "string",
"value": "={{ $('Airtable Schema').all().filter(x => x.json.id == $('Add Inverse LinkTo Field name').item.json.options.linkedTableId)[0].json.fields.filter(x => x.id == $json.level_3_links)[0].options.linkedTableId }}"
},
{
"id": "92042131-dc3f-40d1-a38e-3aede5dec35a",
"name": "level_3_field_id",
"type": "string",
"value": "={{ $('Airtable Schema').all().filter(x => x.json.id == $('Add Inverse LinkTo Field name').item.json.options.linkedTableId)[0].json.fields.filter(x => x.id == $json.level_3_links)[0].options.inverseLinkFieldId }}"
},
{
"id": "e4c1a3b3-592c-477d-82f8-32306cee478d",
"name": "level_2_field_name",
"type": "string",
"value": "={{ $('Airtable Schema').all().filter(x => x.json.id == $('Add Inverse LinkTo Field name').item.json.options.linkedTableId)[0].json.fields.filter(x => x.id == $json.level_3_links)[0].name }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "25d3c6b3-9f3f-4703-9def-ca7435608d10",
"name": "Preparing aggregation",
"type": "n8n-nodes-base.set",
"position": [
5360,
-120
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "f07ee481-b1fe-409a-b620-9cb4d151de31",
"name": "level_2_record",
"type": "object",
"value": "={{ $('Level 2 records').item.json.fields }}"
},
{
"id": "4e49b6a0-8b3b-4c6e-bce6-178d720415dc",
"name": "level_3_records",
"type": "array",
"value": "={{ $json.records.map(x => x.fields) }}"
},
{
"id": "f397d1cb-f5fa-4d9f-956b-ec665ab22992",
"name": "level_2_field_name",
"type": "string",
"value": "={{ $('Prepare HTTP Call').item.json.level_2_field_name }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "47ac8540-6a58-46b5-b690-6beadcbbd52f",
"name": "Code to single field property",
"type": "n8n-nodes-base.code",
"position": [
5800,
-120
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Add a new field called 'myNewField' to the JSON of the item\n\njson = {\"fields\": {}}\ni=0;\nfor (let k of $input.item.json.level_2_field_name) {\n json.fields[k] = $input.item.json.level_3_records[i];\n i++;\n}\n\n\n$input.item.json = json;\n\nreturn $input.item;"
},
"typeVersion": 2
},
{
"id": "1e4f7e9d-923e-4b91-a5a4-3c928f5004a5",
"name": "Merge with original field property",
"type": "n8n-nodes-base.set",
"position": [
6020,
-40
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "ba4874e7-a116-4a8e-9c67-2731e7ebdf06",
"name": "fields",
"type": "object",
"value": "={{ {fields: {...$('Loop Over L2 Records for a given L1 field').item.json.fields, ...$json.fields} } }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "6e45ff3e-0e31-4658-a718-51a1b580b8ef",
"name": "Aggregate to record list",
"type": "n8n-nodes-base.aggregate",
"position": [
4640,
-400
],
"parameters": {
"options": {},
"fieldsToAggregate": {
"fieldToAggregate": [
{
"renameField": true,
"outputFieldName": "records",
"fieldToAggregate": "fields"
}
]
}
},
"typeVersion": 1
},
{
"id": "c791981c-d73f-4af5-b64e-27fec10994bc",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
3480,
-720
],
"parameters": {
"width": 2730,
"height": 1040,
"content": "## Level 3 children\n\nThis is an iteration on each L2 records array having level 3 children to be fetched"
},
"typeVersion": 1
},
{
"id": "ec5ebe98-56f9-4568-afc7-2b5202d205b4",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
800,
180
],
"parameters": {
"width": 440,
"height": 380,
"content": "## Input\n\n```\n[\n {\n \"base_id\": \"appN8nPMGoLNuzUbY\",\n \"table_id\": \"tblLVOwpYIe0fGQ52\",\n \"record_id\": \"reczMh1Pp5l94HdYf\",\n \"level_3\": [\n \"fldRaFra1rLta66cD\",\n \"fld3FxCaYk8AVaEHt\"\n ],\n \"to_html\": true\n }\n]\n```"
},
"typeVersion": 1
},
{
"id": "4d689138-a84e-45e2-9202-757057f6a326",
"name": "Rich Text Fields list",
"type": "n8n-nodes-base.set",
"position": [
5200,
480
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "3137cbad-90c5-4718-a3f4-cdc1fb04cd33",
"name": "richTextFields",
"type": "array",
"value": "={{ $('Airtable Schema').all().map(\n\nx => x.json.fields.filter(x => x.type == \"richText\").map(x => x.name)\n\n).flat() }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "32bfa99d-8675-4bfa-9644-4f0eb10d66a2",
"name": "Markdown to Html",
"type": "n8n-nodes-base.code",
"position": [
5460,
480
],
"parameters": {
"jsCode": "const marked = require('marked');\n\nfunction convertMarkdownToHtml(obj, propertiesToConvert) {\n // Check if the object is an array\n if (Array.isArray(obj)) {\n // If it's an array, loop through each item and recursively call the function\n return obj.map(item => convertMarkdownToHtml(item, propertiesToConvert));\n } else if (typeof obj === 'object') {\n // If it's an object, loop through each property\n for (const key in obj) {\n if (Object.prototype.hasOwnProperty.call(obj, key)) {\n const value = obj[key];\n // Check if the property name is in the array of properties to convert\n if (propertiesToConvert.includes(key)) {\n // Check if the value is a string (potential markdown)\n if (typeof value === 'string') {\n // Convert markdown to HTML using marked library\n obj[key] = marked.parse(value);\n }\n } else {\n // If the property name is not in the array, recursively check if it's an object or array\n if (typeof value === 'object') {\n obj[key] = convertMarkdownToHtml(value, propertiesToConvert);\n }\n }\n }\n }\n return obj;\n } else {\n // If it's not an object or array, return as is (since we can't convert it)\n return obj;\n }\n}\n\nreturn convertMarkdownToHtml($('Insert linked records to originRecord & Clean Field Name').first().json,$('Rich Text Fields list').first().json.richTextFields)\n\n\n\n"
},
"typeVersion": 2
},
{
"id": "737044e7-1263-4ef0-a6b3-2746f4532171",
"name": "If markdown to html",
"type": "n8n-nodes-base.if",
"position": [
4960,
680
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "5ff55a7e-ebb2-4cd7-af12-680b87fd2d53",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ $('Execute Workflow Trigger').first().json.to_html }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "82d7b6f5-a1be-45f1-97b3-0221c5b6263d",
"name": "Merge2",
"type": "n8n-nodes-base.merge",
"position": [
5860,
800
],
"parameters": {
"mode": "combine",
"options": {
"includeUnpaired": true
},
"combineBy": "combineByPosition",
"numberInputs": 3
},
"typeVersion": 3
},
{
"id": "57f90bea-9a0b-4093-83ba-1bd18200b84c",
"name": "Get Airtable Comments",
"type": "n8n-nodes-base.httpRequest",
"position": [
1880,
820
],
"parameters": {
"url": "=https://api.airtable.com/v0/{{ $json.base_id }}/{{ $json.table_id }}/{{ $json.record_id }}/comments",
"options": {},
"authentication": "predefinedCredentialType",
"nodeCredentialType": "airtableTokenApi"
},
"credentials": {
"airtableTokenApi": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "ae6b84ef-940e-497a-8081-a1da8ed7f960",
"name": "Rename comments",
"type": "n8n-nodes-base.set",
"position": [
2100,
820
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "a58e06ab-906f-4cb4-a108-d9839264912e",
"name": "AirtableComments",
"type": "array",
"value": "={{ $json.comments }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "d4d73be8-4d60-47b1-be08-057dc4ae0e98",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
800,
-1340
],
"parameters": {
"color": 4,
"width": 920,
"height": 1500,
"content": "# Airtable Hierarchical Record Fetcher\n\n## Description\n\nThis n8n workflow retrieves an Airtable record along with its related child records in a hierarchical structure. It can fetch up to 3 levels of linked records and assembles them into a comprehensive JSON object, making it ideal for complex data relationships and nested record structures.\n\n## Features\n\n- **Multi-level Record Fetching**: Retrieves parent record, linked child records (level 2), and optionally grandchild records (level 3)\n- **Selective Level 3 Fetching**: Only fetches level 3 records for specified linked fields to optimize performance\n- **Rich Text Processing**: Converts Airtable's pseudo-markdown rich text fields to HTML format\n- **Hierarchical JSON Output**: Organizes all data in a structured, nested JSON format\n- **Flexible Configuration**: Customizable depth and field selection per execution\n\n## Input Parameters\n\nThe workflow accepts a JSON array with the following structure:\n\n```json\n[\n {\n \"base_id\": \"appN8nPMGoLNuzUbY\",\n \"table_id\": \"tblLVOwpYIe0fGQ52\", \n \"record_id\": \"reczMh1Pp5l94HdYf\",\n \"level_3\": [\n \"fldRaFra1rLta66cD\",\n \"fld3FxCaYk8AVaEHt\"\n ],\n \"to_html\": true\n }\n]\n```\n\n### Parameter Details\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `base_id` | string | Yes | Airtable base identifier |\n| `table_id` | string | Yes | Airtable table identifier for the main record |\n| `record_id` | string | Yes | Airtable record identifier to fetch |\n| `level_3` | array | No | Array of field IDs from level 2 records for which to fetch level 3 children |\n| `to_html` | boolean | No | Convert rich text fields from pseudo-markdown to HTML (default: false). This requires `marked` npm package. |\n\n## Output Structure\n\nThe workflow returns a hierarchical JSON object with the following structure:\n\n```json\n{\n \"id\": \"recXXXXXXX\",\n \"field_1\": ...,\n \"field_2\": ...,\n \"level2_child\": [\n {\n \"id\": \"recXXXXXXX\",\n \"field_a\": ...,\n \"field_b\": ...,\n \"level3_child\": [\n {\n \"id\": \"recXXXXXXX\",\n \"field_y\": ...,\n \"field_z\": ...,\n },\n ...\n ]\n },\n ...\n ]\n}\n```"
},
"typeVersion": 1
},
{
"id": "64dd6a5e-20ec-44a3-87d0-aac91b5cd42a",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
5060,
360
],
"parameters": {
"color": 3,
"width": 700,
"height": 280,
"content": "## Converts Airtable Rich Text (pseudo-markdown) to HTML\n \n**This requires `marked` npm package.** \n\nYou can delete these nodes if you don't need the feature"
},
"typeVersion": 1
},
{
"id": "632211fc-312c-4023-b96f-8b2e1eff561e",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
2420,
-120
],
"parameters": {
"width": 860,
"height": 520,
"content": "## Level 2 children\n\nFor each `Link to another record` fields:\n\n- We fetch the linked records array (up to 100 children) thanks to a `filterbyformula` API trick\n- In those level 2 children records, we exclude `link to another record` fields except for fields given in `level_3` workflow input\n"
},
"typeVersion": 1
},
{
"id": "fa4bcdc8-c977-4f4a-89e9-545a97855a38",
"name": "Loop Over L2 records arrays having L3 children to fetch",
"type": "n8n-nodes-base.splitInBatches",
"position": [
3820,
-40
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "f9589f05-4ec5-4060-a5d6-8a4263be8c0b",
"name": "Loop Over L2 Records for a given L1 field",
"type": "n8n-nodes-base.splitInBatches",
"position": [
4480,
-40
],
"parameters": {
"options": {
"reset": "={{ $node[\"Loop Over L2 Records for a given L1 field\"].context[\"done\"] }}"
}
},
"typeVersion": 3
},
{
"id": "d62be593-40bf-4ba2-83ec-e32121a35d18",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
4380,
-540
],
"parameters": {
"color": 2,
"width": 1820,
"height": 740,
"content": "## Level 3 children\n\nThis is an iteration on each record within a record array to fetch its level 3 children"
},
"typeVersion": 1
}
],
"connections": {
"Merge": {
"main": [
[
{
"node": "Loop Over L2 Records for a given L1 field",
"type": "main",
"index": 0
}
]
]
},
"Inputs": {
"main": [
[
{
"node": "Airtable - Get Target Record",
"type": "main",
"index": 0
},
{
"node": "Get Airtable Comments",
"type": "main",
"index": 0
}
]
]
},
"Merge1": {
"main": [
[
{
"node": "Add origin LinkTo",
"type": "main",
"index": 0
}
]
]
},
"Aggregate1": {
"main": [
[
{
"node": "Code to single field property",
"type": "main",
"index": 0
}
]
]
},
"If Has Level 3": {
"main": [
[
{
"node": "Loop Over L2 records arrays having L3 children to fetch",
"type": "main",
"index": 0
}
],
[
{
"node": "Merge1",
"type": "main",
"index": 0
}
]
]
},
"Airtable Schema": {
"main": [
[
{
"node": "Filter Main Table",
"type": "main",
"index": 0
}
]
]
},
"Level 2 records": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
},
"Rename comments": {
"main": [
[
{
"node": "Merge2",
"type": "main",
"index": 2
}
]
]
},
"Markdown to Html": {
"main": [
[
{
"node": "Merge2",
"type": "main",
"index": 0
}
]
]
},
"Split Out Fields": {
"main": [
[
{
"node": "Filter Link To fields",
"type": "main",
"index": 0
}
]
]
},
"Add origin LinkTo": {
"main": [
[
{
"node": "Insert linked records to originRecord & Clean Field Name",
"type": "main",
"index": 0
}
]
]
},
"Filter Main Table": {
"main": [
[
{
"node": "Split Out Fields",
"type": "main",
"index": 0
}
]
]
},
"Prepare HTTP Call": {
"main": [
[
{
"node": "Get L3 Linked records without reverse Link To fields",
"type": "main",
"index": 0
}
]
]
},
"If markdown to html": {
"main": [
[
{
"node": "Rich Text Fields list",
"type": "main",
"index": 0
}
],
[
{
"node": "Merge2",
"type": "main",
"index": 1
}
]
]
},
"Filter Link To fields": {
"main": [
[
{
"node": "Add Inverse LinkTo Field name",
"type": "main",
"index": 0
}
]
]
},
"Get Airtable Comments": {
"main": [
[
{
"node": "Rename comments",
"type": "main",
"index": 0
}
]
]
},
"Preparing aggregation": {
"main": [
[
{
"node": "Aggregate1",
"type": "main",
"index": 0
}
]
]
},
"Rich Text Fields list": {
"main": [
[
{
"node": "Markdown to Html",
"type": "main",
"index": 0
}
]
]
},
"Aggregate to record list": {
"main": [
[
{
"node": "Loop Over L2 records arrays having L3 children to fetch",
"type": "main",
"index": 0
}
]
]
},
"Execute Workflow Trigger": {
"main": [
[
{
"node": "Inputs",
"type": "main",
"index": 0
}
]
]
},
"Airtable - Get Target Record": {
"main": [
[
{
"node": "Airtable Schema",
"type": "main",
"index": 0
}
]
]
},
"Split Out L3 Potential Links": {
"main": [
[
{
"node": "Prepare HTTP Call",
"type": "main",
"index": 0
}
]
]
},
"Add Inverse LinkTo Field name": {
"main": [
[
{
"node": "Get Linked records without Link To fields Except for Level 3",
"type": "main",
"index": 0
}
]
]
},
"Code to single field property": {
"main": [
[
{
"node": "Merge with original field property",
"type": "main",
"index": 0
}
]
]
},
"Merge with original field property": {
"main": [
[
{
"node": "Loop Over L2 Records for a given L1 field",
"type": "main",
"index": 0
}
]
]
},
"Repeat L3 links of current L2 table": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
},
"Loop Over L2 Records for a given L1 field": {
"main": [
[
{
"node": "Aggregate to record list",
"type": "main",
"index": 0
}
],
[
{
"node": "Split Out L3 Potential Links",
"type": "main",
"index": 0
}
]
]
},
"Get L3 Linked records without reverse Link To fields": {
"main": [
[
{
"node": "Preparing aggregation",
"type": "main",
"index": 0
}
]
]
},
"Loop Over L2 records arrays having L3 children to fetch": {
"main": [
[
{
"node": "Merge1",
"type": "main",
"index": 1
}
],
[
{
"node": "Repeat L3 links of current L2 table",
"type": "main",
"index": 0
},
{
"node": "Level 2 records",
"type": "main",
"index": 0
}
]
]
},
"Insert linked records to originRecord & Clean Field Name": {
"main": [
[
{
"node": "If markdown to html",
"type": "main",
"index": 0
}
]
]
},
"Get Linked records without Link To fields Except for Level 3": {
"main": [
[
{
"node": "If Has Level 3",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
airtableTokenApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This n8n workflow retrieves an Airtable record along with its related child records in a hierarchical structure. It can fetch up to 3 levels of linked records and assembles them into a comprehensive JSON object, making it ideal for complex data relationships and nested record…
Source: https://n8n.io/workflows/5750/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Lmchatopenai Workflow. Uses noOp, stickyNote, executeWorkflowTrigger, airtable. Event-driven trigger; 41 nodes.
d16-Web-Scraper-Data-Flow. Uses httpRequest, airtable, executeWorkflowTrigger. Event-driven trigger; 20 nodes.
Web-Scraper-Data-Flow. Uses httpRequest, airtable, executeWorkflowTrigger. Event-driven trigger; 19 nodes.
d21-set. Uses httpRequest, airtable, executeWorkflowTrigger. Event-driven trigger; 19 nodes.
Gemini - Video Analysis. Uses googleDrive, googleDriveTrigger, executeWorkflowTrigger, httpRequest. Event-driven trigger; 17 nodes.