This workflow follows the Airtable → OpenAI 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 →
{
"name": "Book table",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "0119b32c-b257-4bcb-a78c-a4016640b844",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
0,
0
],
"id": "f703b458-798b-41f7-92c9-f505bbdd60ac",
"name": "Webhook"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={\n \"results\":[\n {\n \"toolCallId\":\"{{ $('Webhook').first().json.body.message.toolCalls[0].id }}\",\n \"result\":\"the table has been reserved\"\n }\n ]\n}",
"options": {}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
2020,
0
],
"id": "0ce5bb31-ec45-4eab-a6ac-71ad5afc7301",
"name": "Respond to Webhook"
},
{
"parameters": {
"operation": "upsert",
"base": {
"__rl": true,
"value": "appxtRRlb5NSZiaxQ",
"mode": "list",
"cachedResultName": "Restaurant_Management",
"cachedResultUrl": "https://airtable.com/appxtRRlb5NSZiaxQ"
},
"table": {
"__rl": true,
"value": "tblEfvAEJnuRjzKSR",
"mode": "list",
"cachedResultName": "Reservations",
"cachedResultUrl": "https://airtable.com/appxtRRlb5NSZiaxQ/tblEfvAEJnuRjzKSR"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"Guests": "={{ $('Edit Fields').item.json.guests }}",
"Date": "={{ $('formattedDate').item.json.formattedDate }}",
"Table ID": "={{ $('suitableTables').item.json.table }}",
"Status": "Confirmed",
"Email": "={{ $('Edit Fields').item.json.email }}",
"Name": "={{ $('Edit Fields').item.json.name }}",
"Notes": "={{ $('Edit Fields').item.json.notes }}",
"Time": "={{ $json.requestedTime }}",
"Res ID": "=RES{{ Math.floor(Math.random() * 100000) }}"
},
"matchingColumns": [
"Res ID"
],
"schema": [
{
"id": "id",
"displayName": "id",
"required": false,
"defaultMatch": true,
"display": true,
"type": "string",
"readOnly": true,
"removed": false
},
{
"id": "Res ID",
"displayName": "Res ID",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "Date",
"displayName": "Date",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"display": true,
"type": "options",
"options": [
{
"name": "2024-11-29",
"value": "2024-11-29"
},
{
"name": "2024-11-30",
"value": "2024-11-30"
},
{
"name": "2024-12-01",
"value": "2024-12-01"
},
{
"name": "2024-12-02",
"value": "2024-12-02"
},
{
"name": "2024-12-03",
"value": "2024-12-03"
},
{
"name": "2024-12-04",
"value": "2024-12-04"
},
{
"name": "2024-12-05",
"value": "2024-12-05"
},
{
"name": "2024-12-06",
"value": "2024-12-06"
},
{
"name": "2024-12-07",
"value": "2024-12-07"
},
{
"name": "2024-12-08",
"value": "2024-12-08"
},
{
"name": "2024-12-09",
"value": "2024-12-09"
},
{
"name": "2024-12-10",
"value": "2024-12-10"
}
],
"readOnly": false,
"removed": false
},
{
"id": "Time",
"displayName": "Time",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "Table ID",
"displayName": "Table ID",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "Guests",
"displayName": "Guests",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"display": true,
"type": "number",
"readOnly": false,
"removed": false
},
{
"id": "Name",
"displayName": "Name",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "Email",
"displayName": "Email",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "Phone",
"displayName": "Phone",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "Status",
"displayName": "Status",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"display": true,
"type": "options",
"options": [
{
"name": "Confirmed",
"value": "Confirmed"
}
],
"readOnly": false,
"removed": false
},
{
"id": "Notes",
"displayName": "Notes",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"display": true,
"type": "string",
"readOnly": false,
"removed": false
},
{
"id": "updatedTime",
"displayName": "updatedTime",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"display": true,
"type": "string",
"readOnly": true,
"removed": true
},
{
"id": "Table_Availability",
"displayName": "Table_Availability",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"display": true,
"type": "array",
"readOnly": false,
"removed": false
},
{
"id": "timeSlots",
"displayName": "timeSlots",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"display": true,
"type": "array",
"readOnly": false,
"removed": false
},
{
"id": "table",
"displayName": "table",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"display": true,
"type": "array",
"readOnly": false,
"removed": false
},
{
"id": "Date (from timeSlots)",
"displayName": "Date (from timeSlots)",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"display": true,
"type": "string",
"readOnly": true,
"removed": true
},
{
"id": "Time Slot (from timeSlots)",
"displayName": "Time Slot (from timeSlots)",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"display": true,
"type": "string",
"readOnly": true,
"removed": true
}
]
},
"options": {}
},
"type": "n8n-nodes-base.airtable",
"typeVersion": 2.1,
"position": [
1660,
0
],
"id": "cc285bc5-55f2-43b7-bc2e-97c34a29778e",
"name": "Airtable",
"credentials": {
"airtableTokenApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"jsCode": "const guests = $input.first().json.guests\n\n// Get suitable tables based on party size\nfunction getSuitableTables(guests) {\n if (guests <= 2) return ['T1', 'T2'];\n if (guests <= 4) return ['T3', 'T4'];\n if (guests <= 6) return ['T5'];\n return [];\n}\n\nconst suitableTables = getSuitableTables(guests);\n\n\nreturn {json: {\n table: suitableTables[0],\n}};"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
560,
0
],
"id": "c0b4dab9-ae41-43ea-a703-37da742ab5ab",
"name": "suitableTables",
"notesInFlow": true,
"notes": "We get the suitable tables for a given number of guests\nand we create a filter to apply in the formula for airtables in the next node"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "4529b69f-9edd-4558-989f-440cf5ade08d",
"name": "guests",
"value": "={{ $json.body.message.toolCalls[0].function.arguments.guests }}",
"type": "number"
},
{
"id": "6a105262-9cd4-403c-a6ed-28e1ee9dba0f",
"name": "name",
"value": "={{ $json.body.message.toolCalls[0].function.arguments.name }}",
"type": "string"
},
{
"id": "5c2f4e3c-f6b0-414a-8bf8-ed6c24c96846",
"name": "date",
"value": "={{ $json.body.message.toolCalls[0].function.arguments.date }}",
"type": "string"
},
{
"id": "697476d2-f635-4638-a578-a1b245d74a71",
"name": "notes",
"value": "={{ $json.body.message.toolCalls[0].function.arguments.notes }}",
"type": "string"
},
{
"id": "a9f9d8d6-a568-40bf-9aba-64276d03ee8f",
"name": "email",
"value": "={{ $json.body.message.toolCalls[0].function.arguments.email }}",
"type": "string"
},
{
"id": "38eac618-1267-42ba-bace-d5bc490404d7",
"name": "time",
"value": "={{ $json.body.message.toolCalls[0].function.arguments.time }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
300,
0
],
"id": "22630b8a-9fbc-41c5-840f-dc63b705dc16",
"name": "Edit Fields"
},
{
"parameters": {
"modelId": {
"__rl": true,
"value": "gpt-4o-mini",
"mode": "list",
"cachedResultName": "GPT-4O-MINI"
},
"messages": {
"values": [
{
"content": "=You are a date parsing assistant. Today's date is {{$today}}. Your task is to convert natural language date expressions into YYYY-MM-DD format.\nRules:\n\nAlways output only the date in YYYY-MM-DD format\nIf the year isn't specified, assume the nearest future date\nFor \"next [day]\", select the next occurrence after the upcoming one\nFor relative dates (tomorrow, day after tomorrow), calculate from today's date\nFor numeric dates (e.g., \"15th\"), assume the nearest future occurrence\nFor month names, use the next occurrence if the day has passed\n\nInput examples and expected outputs (assuming today is {{$today}}):\n\n\"tomorrow\" \u2192 [calculate tomorrow's date]\n\"next monday\" \u2192 [calculate second monday from today]\n\"this friday\" \u2192 [calculate next friday]\n\"day after tomorrow\" \u2192 [calculate date after tomorrow]\n\"in 3 days\" \u2192 [calculate date 3 days from today]\n\"next week tuesday\" \u2192 [calculate next tuesday]\n\"december 25th\" \u2192 [calculate next December 25th]\n\"25/12\" \u2192 [calculate next December 25th]\n\"25th of next month\" \u2192 [calculate 25th of next month]\n\"first tuesday of next month\" \u2192 [calculate accordingly]\n\"end of this month\" \u2192 [calculate last day of current month]\n\"2024-12-25\" \u2192 2024-12-25\n\nOnly respond with the date in YYYY-MM-DD format. No explanations or additional text.\nInput: {{ $('Edit Fields').item.json.date }}"
}
]
},
"jsonOutput": true,
"options": {
"temperature": 0
}
},
"type": "@n8n/n8n-nodes-langchain.openAi",
"typeVersion": 1.7,
"position": [
800,
0
],
"id": "033c1fc4-eb9e-44d9-97d3-a8ca30733a98",
"name": "parse date",
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "0637d1d3-5eaf-449b-8b0a-82db04f60609",
"name": "formattedDate",
"value": "={{ $json.message.content.date }}",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
1180,
0
],
"id": "677c567f-4f7f-4146-886d-6275d6331cc0",
"name": "formattedDate"
},
{
"parameters": {
"jsCode": "\nfunction formatTime(timeStr) {\n // Remove any spaces\n timeStr = timeStr.toLowerCase().replace(/\\s/g, '');\n \n // Handle cases like \"7:30pm\", \"7pm\", \"19:30\", \"7\", \"7:30\"\n let hours, minutes;\n \n if (timeStr.includes('pm')) {\n timeStr = timeStr.replace('pm', '');\n let [h, m] = timeStr.split(':').map(Number);\n hours = (h === 12 ? 12 : h + 12);\n minutes = m || 0;\n } else if (timeStr.includes('am')) {\n timeStr = timeStr.replace('am', '');\n let [h, m] = timeStr.split(':').map(Number);\n hours = (h === 12 ? 0 : h);\n minutes = m || 0;\n } else {\n // Assume 24-hour format or just hours\n let [h, m] = timeStr.split(':').map(Number);\n hours = h;\n minutes = m || 0;\n }\n \n // Format with leading zeros\n return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;\n}\nlet requestedTime =$('Webhook').first().json.body.message.toolCalls[0].function.arguments.time\nrequestedTime = formatTime(requestedTime);\n\nreturn {\n json:{\n requestedTime\n }\n}"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1460,
0
],
"id": "87431d9d-385c-436e-b914-bfc7ffd00d11",
"name": "parseTime"
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
},
"Airtable": {
"main": [
[
{
"node": "Respond to Webhook",
"type": "main",
"index": 0
}
]
]
},
"suitableTables": {
"main": [
[
{
"node": "parse date",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields": {
"main": [
[
{
"node": "suitableTables",
"type": "main",
"index": 0
}
]
]
},
"parse date": {
"main": [
[
{
"node": "formattedDate",
"type": "main",
"index": 0
}
]
]
},
"formattedDate": {
"main": [
[
{
"node": "parseTime",
"type": "main",
"index": 0
}
]
]
},
"parseTime": {
"main": [
[
{
"node": "Airtable",
"type": "main",
"index": 0
}
]
]
}
},
"active": true,
"settings": {
"executionOrder": "v1"
},
"versionId": "7ea47a60-e230-4407-8973-246c852a4256",
"meta": {
"templateCredsSetupCompleted": true
},
"id": "AyqUqaJJ3VRsD2Jb",
"tags": [
{
"createdAt": "2025-02-26T09:17:48.643Z",
"updatedAt": "2025-02-26T09:17:48.643Z",
"id": "2JZs1TZAuBnwITKy",
"name": "restaurant agent"
}
]
}
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.
airtableTokenApiopenAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Book table. Uses airtable, openAi. Webhook trigger; 8 nodes.
Source: https://github.com/Ayushsinha2004/new_agent/blob/4f0adc05e2deeaabac2dcbe82940ddf4ca6a573c/n8n/Book_table.json — 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.
This powerful n8n automation workflow is designed to execute advanced B2B lead enrichment and hyper-personalization for cold email outreach. By orchestrating a complex chain of data scraping, AI analy
This template is perfect for e-commerce entrepreneurs, marketers, agencies, and creative teams who want to turn simple product photos and short descriptions into professional flyers or product videos—
This n8n template demonstrates how to capture inbound leads from a form, qualify them with OpenAI, and route the hottest ones to a Bland AI voice agent that calls them back, books a meeting on Google
AI-Powered Fake Review Detection Workflow Using n8n & Airtable. Uses httpRequest, airtable, openAi, slack. Webhook trigger; 27 nodes.
This workflow automatically monitors Facebook Group posts, analyzes them using AI, detects policy violations, logs incidents, notifies moderators and automatically hides high-severity posts to keep th