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": "sync-state",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "sync-state",
"responseMode": "responseNode",
"options": {}
},
"id": "a1000000-0000-0000-0000-000000000001",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
240,
480
]
},
{
"parameters": {
"rules": {
"values": [
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose"
},
"conditions": [
{
"id": "c1",
"leftValue": "={{ ($json.body && $json.body.action) || $json.action || '' }}",
"rightValue": "getAll",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "getAll"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose"
},
"conditions": [
{
"id": "c2",
"leftValue": "={{ ($json.body && $json.body.action) || $json.action || '' }}",
"rightValue": "createStudent",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "createStudent"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose"
},
"conditions": [
{
"id": "c3",
"leftValue": "={{ ($json.body && $json.body.action) || $json.action || '' }}",
"rightValue": "deleteStudent",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "deleteStudent"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose"
},
"conditions": [
{
"id": "c4",
"leftValue": "={{ ($json.body && $json.body.action) || $json.action || '' }}",
"rightValue": "saveLibraryItem",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "saveLibraryItem"
},
{
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "loose"
},
"conditions": [
{
"id": "c5",
"leftValue": "={{ ($json.body && $json.body.action) || $json.action || '' }}",
"rightValue": "saveAttempt",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"renameOutput": true,
"outputKey": "saveAttempt"
}
]
},
"options": {
"fallbackOutput": "extra",
"ignoreCase": true
}
},
"id": "a2000000-0000-0000-0000-000000000002",
"name": "Action Switch",
"type": "n8n-nodes-base.switch",
"typeVersion": 3.2,
"position": [
460,
480
]
},
{
"parameters": {
"operation": "search",
"base": {
"__rl": true,
"value": "appZQ5D66jzxmfwOm",
"mode": "id"
},
"table": {
"__rl": true,
"value": "tblJ01dBWOiV1cnT6",
"mode": "id"
},
"options": {}
},
"id": "a3000000-0000-0000-0000-000000000003",
"name": "Students List",
"type": "n8n-nodes-base.airtable",
"typeVersion": 2.1,
"position": [
700,
100
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"mode": "runOnceForAllItems",
"language": "javaScript",
"jsCode": "const items = $input.all();\nconst students = (items || []).map(it => {\n const j = (it && it.json) || {};\n const f = j.fields || j || {};\n const grade = Number(f.grade);\n return {\n id: j.id || j.recordId || '',\n name: f.name || '',\n grade: Number.isFinite(grade) && grade > 0 ? grade : 1,\n country: f.country || 'UK',\n subject: f.subject || '',\n parentEmail: f.parent_email || undefined,\n avatarColor: f.avatar_color || '#B6F2D7',\n };\n});\nreturn [{ json: { _students: students } }];"
},
"id": "a3100000-0000-0000-0000-000000000031",
"name": "Stash students",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
880,
100
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"operation": "search",
"base": {
"__rl": true,
"value": "appZQ5D66jzxmfwOm",
"mode": "id"
},
"table": {
"__rl": true,
"value": "tblibktOQqFLFfwot",
"mode": "id"
},
"options": {}
},
"id": "a4000000-0000-0000-0000-000000000004",
"name": "LibraryItems List",
"type": "n8n-nodes-base.airtable",
"typeVersion": 2.1,
"position": [
1060,
100
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"mode": "runOnceForAllItems",
"language": "javaScript",
"jsCode": "const items = $input.all();\nconst safeParse = (s, fb) => { if (s === null || s === undefined || s === '') return fb; if (typeof s !== 'string') return s; try { return JSON.parse(s); } catch { return fb; } };\nconst libraryItems = (items || []).map(it => {\n const j = (it && it.json) || {};\n const f = j.fields || j || {};\n return {\n id: j.id || j.recordId || '',\n type: f.type || 'diagnostic',\n title: f.title || '',\n studentId: (Array.isArray(f.student) ? f.student[0] : f.student) || '',\n payload: safeParse(f.payload, {}),\n createdAt: f.created_at || j.createdTime || new Date().toISOString(),\n };\n});\nlet prev = {};\ntry { prev = $('Stash students').first().json || {}; } catch {}\nreturn [{ json: { _students: prev._students || [], _libraryItems: libraryItems } }];"
},
"id": "a4100000-0000-0000-0000-000000000041",
"name": "Stash library",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1240,
100
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"operation": "search",
"base": {
"__rl": true,
"value": "appZQ5D66jzxmfwOm",
"mode": "id"
},
"table": {
"__rl": true,
"value": "tbl83UCCmYxy7r7Ey",
"mode": "id"
},
"options": {}
},
"id": "a5000000-0000-0000-0000-000000000005",
"name": "QuizAttempts List",
"type": "n8n-nodes-base.airtable",
"typeVersion": 2.1,
"position": [
1420,
100
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"mode": "runOnceForAllItems",
"language": "javaScript",
"jsCode": "const items = $input.all();\nconst safeParse = (s, fb) => { if (s === null || s === undefined || s === '') return fb; if (typeof s !== 'string') return s; try { return JSON.parse(s); } catch { return fb; } };\nconst attempts = (items || []).map(it => {\n const j = (it && it.json) || {};\n const f = j.fields || j || {};\n return {\n id: j.id || j.recordId || '',\n studentId: (Array.isArray(f.student) ? f.student[0] : f.student) || '',\n libraryItemId: (Array.isArray(f.library_item) ? f.library_item[0] : f.library_item) || '',\n score: Number.isFinite(Number(f.score)) ? Number(f.score) : 0,\n skills: safeParse(f.skills_json, {}),\n strengths: safeParse(f.strengths, []),\n weaknesses: safeParse(f.weaknesses, []),\n recommendations: safeParse(f.recommendations, []),\n analysisText: f.analysis_text || '',\n createdAt: f.created_at || j.createdTime || new Date().toISOString(),\n };\n});\nlet prev = {};\ntry { prev = $('Stash library').first().json || {}; } catch {}\nreturn [{ json: { students: prev._students || [], libraryItems: prev._libraryItems || [], attempts } }];"
},
"id": "a6000000-0000-0000-0000-000000000006",
"name": "Map getAll",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1600,
100
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ $json }}",
"options": {
"responseCode": 200
}
},
"id": "a7000000-0000-0000-0000-000000000007",
"name": "Respond getAll",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
1800,
100
]
},
{
"parameters": {
"mode": "runOnceForAllItems",
"language": "javaScript",
"jsCode": "const p = (($json && $json.body && $json.body.payload) || ($json && $json.payload)) || {};\nif (!p || typeof p !== 'object') throw new Error('createStudent: missing payload');\nif (!p.name || !String(p.name).trim()) throw new Error('createStudent: name is required');\nconst grade = Number(p.grade);\nconst fields = {\n name: String(p.name).trim(),\n grade: Number.isFinite(grade) && grade > 0 ? grade : 1,\n country: p.country || 'UK',\n subject: p.subject || '',\n avatar_color: p.avatarColor || '#B6F2D7',\n};\nif (p.parentEmail) fields.parent_email = String(p.parentEmail).trim();\nreturn [{ json: fields }];"
},
"id": "b1000000-0000-0000-0000-000000000001",
"name": "Build student fields",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
700,
460
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"operation": "create",
"base": {
"__rl": true,
"value": "appZQ5D66jzxmfwOm",
"mode": "id"
},
"table": {
"__rl": true,
"value": "tblJ01dBWOiV1cnT6",
"mode": "id"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"name": "={{ $json.name }}",
"grade": "={{ $json.grade }}",
"country": "={{ $json.country }}",
"subject": "={{ $json.subject }}",
"parent_email": "={{ $json.parent_email }}",
"avatar_color": "={{ $json.avatar_color }}"
},
"matchingColumns": [],
"schema": [
{
"id": "name",
"displayName": "name",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"type": "string",
"display": true,
"removed": false
},
{
"id": "grade",
"displayName": "grade",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"type": "number",
"display": true,
"removed": false
},
{
"id": "country",
"displayName": "country",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"type": "string",
"display": true,
"removed": false
},
{
"id": "subject",
"displayName": "subject",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"type": "string",
"display": true,
"removed": false
},
{
"id": "parent_email",
"displayName": "parent_email",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"type": "string",
"display": true,
"removed": false
},
{
"id": "avatar_color",
"displayName": "avatar_color",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"type": "string",
"display": true,
"removed": false
}
]
},
"options": {
"typecast": true
}
},
"id": "b2000000-0000-0000-0000-000000000002",
"name": "Create Student",
"type": "n8n-nodes-base.airtable",
"typeVersion": 2.1,
"position": [
940,
460
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"mode": "runOnceForAllItems",
"language": "javaScript",
"jsCode": "const it = $input.first();\nconst j = (it && it.json) || {};\nconst f = j.fields || j || {};\nconst grade = Number(f.grade);\nreturn [{\n json: {\n id: j.id || j.recordId || '',\n name: f.name || '',\n grade: Number.isFinite(grade) && grade > 0 ? grade : 1,\n country: f.country || 'UK',\n subject: f.subject || '',\n parentEmail: f.parent_email || undefined,\n avatarColor: f.avatar_color || '#B6F2D7',\n },\n}];"
},
"id": "b3000000-0000-0000-0000-000000000003",
"name": "Map student response",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1180,
460
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ $json }}",
"options": {
"responseCode": 200
}
},
"id": "b4000000-0000-0000-0000-000000000004",
"name": "Respond createStudent",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
1420,
460
]
},
{
"parameters": {
"mode": "runOnceForAllItems",
"language": "javaScript",
"jsCode": "const id = (($json && $json.body && $json.body.payload) || ($json && $json.payload)) || '';\nif (!id || typeof id !== 'string') throw new Error('deleteStudent: payload must be a record id string');\nreturn [{ json: { id } }];"
},
"id": "c0500000-0000-0000-0000-000000000005",
"name": "Build delete id",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
500,
620
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"operation": "delete",
"base": {
"__rl": true,
"value": "appZQ5D66jzxmfwOm",
"mode": "id"
},
"table": {
"__rl": true,
"value": "tblJ01dBWOiV1cnT6",
"mode": "id"
},
"id": "={{ $json.id }}"
},
"id": "c1000000-0000-0000-0000-000000000001",
"name": "Delete Student",
"type": "n8n-nodes-base.airtable",
"typeVersion": 2.1,
"position": [
700,
620
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ { \"success\": true } }}",
"options": {
"responseCode": 200
}
},
"id": "c2000000-0000-0000-0000-000000000002",
"name": "Respond deleteStudent",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
940,
620
]
},
{
"parameters": {
"mode": "runOnceForAllItems",
"language": "javaScript",
"jsCode": "const p = (($json && $json.body && $json.body.payload) || ($json && $json.payload)) || {};\nif (!p || typeof p !== 'object') throw new Error('saveLibraryItem: missing payload');\nif (!p.title || !String(p.title).trim()) throw new Error('saveLibraryItem: title is required');\nif (!p.type) throw new Error('saveLibraryItem: type is required');\nconst payloadStr = typeof p.payload === 'string' ? p.payload : JSON.stringify(p.payload || {});\nreturn [{\n json: {\n type: p.type,\n title: String(p.title).trim(),\n student: p.studentId ? [p.studentId] : [],\n payload: payloadStr,\n },\n}];"
},
"id": "d1000000-0000-0000-0000-000000000001",
"name": "Build library fields",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
700,
780
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"operation": "create",
"base": {
"__rl": true,
"value": "appZQ5D66jzxmfwOm",
"mode": "id"
},
"table": {
"__rl": true,
"value": "tblibktOQqFLFfwot",
"mode": "id"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"type": "={{ $json.type }}",
"title": "={{ $json.title }}",
"student": "={{ $json.student }}",
"payload": "={{ $json.payload }}"
},
"matchingColumns": [],
"schema": [
{
"id": "type",
"displayName": "type",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"type": "string",
"display": true,
"removed": false
},
{
"id": "title",
"displayName": "title",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"type": "string",
"display": true,
"removed": false
},
{
"id": "student",
"displayName": "student",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"type": "array",
"display": true,
"removed": false
},
{
"id": "payload",
"displayName": "payload",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"type": "string",
"display": true,
"removed": false
}
]
},
"options": {
"typecast": true
}
},
"id": "d2000000-0000-0000-0000-000000000002",
"name": "Create LibraryItem",
"type": "n8n-nodes-base.airtable",
"typeVersion": 2.1,
"position": [
940,
780
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"mode": "runOnceForAllItems",
"language": "javaScript",
"jsCode": "const it = $input.first();\nconst j = (it && it.json) || {};\nconst f = j.fields || j || {};\nconst safeParse = (s, fb) => { if (s === null || s === undefined || s === '') return fb; if (typeof s !== 'string') return s; try { return JSON.parse(s); } catch { return fb; } };\nreturn [{\n json: {\n id: j.id || j.recordId || '',\n type: f.type || 'diagnostic',\n title: f.title || '',\n studentId: (Array.isArray(f.student) ? f.student[0] : f.student) || '',\n payload: safeParse(f.payload, {}),\n createdAt: f.created_at || j.createdTime || new Date().toISOString(),\n },\n}];"
},
"id": "d3000000-0000-0000-0000-000000000003",
"name": "Map library response",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1180,
780
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ $json }}",
"options": {
"responseCode": 200
}
},
"id": "d4000000-0000-0000-0000-000000000004",
"name": "Respond saveLibraryItem",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
1420,
780
]
},
{
"parameters": {
"mode": "runOnceForAllItems",
"language": "javaScript",
"jsCode": "const p = (($json && $json.body && $json.body.payload) || ($json && $json.payload)) || {};\nif (!p || typeof p !== 'object') throw new Error('saveAttempt: missing payload');\nconst score = Number(p.score);\nreturn [{\n json: {\n student: p.studentId ? [p.studentId] : [],\n library_item: p.libraryItemId ? [p.libraryItemId] : [],\n score: Number.isFinite(score) ? score : 0,\n skills_json: JSON.stringify(p.skills || {}),\n strengths: JSON.stringify(p.strengths || []),\n weaknesses: JSON.stringify(p.weaknesses || []),\n recommendations: JSON.stringify(p.recommendations || []),\n analysis_text: p.analysisText || '',\n },\n}];"
},
"id": "e1000000-0000-0000-0000-000000000001",
"name": "Build attempt fields",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
700,
940
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"operation": "create",
"base": {
"__rl": true,
"value": "appZQ5D66jzxmfwOm",
"mode": "id"
},
"table": {
"__rl": true,
"value": "tbl83UCCmYxy7r7Ey",
"mode": "id"
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"student": "={{ $json.student }}",
"library_item": "={{ $json.library_item }}",
"score": "={{ $json.score }}",
"skills_json": "={{ $json.skills_json }}",
"strengths": "={{ $json.strengths }}",
"weaknesses": "={{ $json.weaknesses }}",
"recommendations": "={{ $json.recommendations }}",
"analysis_text": "={{ $json.analysis_text }}"
},
"matchingColumns": [],
"schema": [
{
"id": "student",
"displayName": "student",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"type": "array",
"display": true,
"removed": false
},
{
"id": "library_item",
"displayName": "library_item",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"type": "array",
"display": true,
"removed": false
},
{
"id": "score",
"displayName": "score",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"type": "number",
"display": true,
"removed": false
},
{
"id": "skills_json",
"displayName": "skills_json",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"type": "string",
"display": true,
"removed": false
},
{
"id": "strengths",
"displayName": "strengths",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"type": "string",
"display": true,
"removed": false
},
{
"id": "weaknesses",
"displayName": "weaknesses",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"type": "string",
"display": true,
"removed": false
},
{
"id": "recommendations",
"displayName": "recommendations",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"type": "string",
"display": true,
"removed": false
},
{
"id": "analysis_text",
"displayName": "analysis_text",
"required": false,
"defaultMatch": false,
"canBeUsedToMatch": true,
"type": "string",
"display": true,
"removed": false
}
]
},
"options": {
"typecast": true
}
},
"id": "e2000000-0000-0000-0000-000000000002",
"name": "Create QuizAttempt",
"type": "n8n-nodes-base.airtable",
"typeVersion": 2.1,
"position": [
940,
940
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"mode": "runOnceForAllItems",
"language": "javaScript",
"jsCode": "const it = $input.first();\nconst j = (it && it.json) || {};\nconst f = j.fields || j || {};\nconst safeParse = (s, fb) => { if (s === null || s === undefined || s === '') return fb; if (typeof s !== 'string') return s; try { return JSON.parse(s); } catch { return fb; } };\nconst score = Number(f.score);\nreturn [{\n json: {\n id: j.id || j.recordId || '',\n studentId: (Array.isArray(f.student) ? f.student[0] : f.student) || '',\n libraryItemId: (Array.isArray(f.library_item) ? f.library_item[0] : f.library_item) || '',\n score: Number.isFinite(score) ? score : 0,\n skills: safeParse(f.skills_json, {}),\n strengths: safeParse(f.strengths, []),\n weaknesses: safeParse(f.weaknesses, []),\n recommendations: safeParse(f.recommendations, []),\n analysisText: f.analysis_text || '',\n createdAt: f.created_at || j.createdTime || new Date().toISOString(),\n },\n}];"
},
"id": "e3000000-0000-0000-0000-000000000003",
"name": "Map attempt response",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1180,
940
],
"onError": "continueErrorOutput"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ $json }}",
"options": {
"responseCode": 200
}
},
"id": "e4000000-0000-0000-0000-000000000004",
"name": "Respond saveAttempt",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
1420,
940
]
},
{
"parameters": {
"mode": "runOnceForAllItems",
"language": "javaScript",
"jsCode": "const data = $json || {};\nlet msg = 'sync-state: server error';\nif (data && data.error) {\n if (typeof data.error === 'string') msg = data.error;\n else if (data.error.message) msg = data.error.message;\n else if (data.error.description) msg = data.error.description;\n else msg = JSON.stringify(data.error).slice(0, 400);\n} else if (data && data.message) {\n msg = data.message;\n}\nreturn [{ json: { error: msg } }];"
},
"id": "f1000000-0000-0000-0000-000000000001",
"name": "Build Error Common",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1600,
1140
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ $json }}",
"options": {
"responseCode": 500
}
},
"id": "f2000000-0000-0000-0000-000000000002",
"name": "Respond Error",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
1800,
1140
]
},
{
"parameters": {
"mode": "runOnceForAllItems",
"language": "javaScript",
"jsCode": "const action = ($json && $json.body && $json.body.action) || ($json && $json.action) || '';\nreturn [{ json: { error: 'Unknown action: ' + (action ? JSON.stringify(action) : '(empty body)') + '. Expected one of: getAll, createStudent, deleteStudent, saveLibraryItem, saveAttempt.' } }];"
},
"id": "f3000000-0000-0000-0000-000000000003",
"name": "Build Unknown Action Error",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
700,
1300
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ $json }}",
"options": {
"responseCode": 400
}
},
"id": "f4000000-0000-0000-0000-000000000004",
"name": "Respond Unknown Action",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
940,
1300
]
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "Action Switch",
"type": "main",
"index": 0
}
]
]
},
"Action Switch": {
"main": [
[
{
"node": "Students List",
"type": "main",
"index": 0
}
],
[
{
"node": "Build student fields",
"type": "main",
"index": 0
}
],
[
{
"node": "Build delete id",
"type": "main",
"index": 0
}
],
[
{
"node": "Build library fields",
"type": "main",
"index": 0
}
],
[
{
"node": "Build attempt fields",
"type": "main",
"index": 0
}
],
[
{
"node": "Build Unknown Action Error",
"type": "main",
"index": 0
}
]
]
},
"Students List": {
"main": [
[
{
"node": "Stash students",
"type": "main",
"index": 0
}
],
[
{
"node": "Build Error Common",
"type": "main",
"index": 0
}
]
]
},
"Stash students": {
"main": [
[
{
"node": "LibraryItems List",
"type": "main",
"index": 0
}
],
[
{
"node": "Build Error Common",
"type": "main",
"index": 0
}
]
]
},
"LibraryItems List": {
"main": [
[
{
"node": "Stash library",
"type": "main",
"index": 0
}
],
[
{
"node": "Build Error Common",
"type": "main",
"index": 0
}
]
]
},
"Stash library": {
"main": [
[
{
"node": "QuizAttempts List",
"type": "main",
"index": 0
}
],
[
{
"node": "Build Error Common",
"type": "main",
"index": 0
}
]
]
},
"QuizAttempts List": {
"main": [
[
{
"node": "Map getAll",
"type": "main",
"index": 0
}
],
[
{
"node": "Build Error Common",
"type": "main",
"index": 0
}
]
]
},
"Map getAll": {
"main": [
[
{
"node": "Respond getAll",
"type": "main",
"index": 0
}
],
[
{
"node": "Build Error Common",
"type": "main",
"index": 0
}
]
]
},
"Build student fields": {
"main": [
[
{
"node": "Create Student",
"type": "main",
"index": 0
}
],
[
{
"node": "Build Error Common",
"type": "main",
"index": 0
}
]
]
},
"Create Student": {
"main": [
[
{
"node": "Map student response",
"type": "main",
"index": 0
}
],
[
{
"node": "Build Error Common",
"type": "main",
"index": 0
}
]
]
},
"Map student response": {
"main": [
[
{
"node": "Respond createStudent",
"type": "main",
"index": 0
}
],
[
{
"node": "Build Error Common",
"type": "main",
"index": 0
}
]
]
},
"Build delete id": {
"main": [
[
{
"node": "Delete Student",
"type": "main",
"index": 0
}
],
[
{
"node": "Build Error Common",
"type": "main",
"index": 0
}
]
]
},
"Delete Student": {
"main": [
[
{
"node": "Respond deleteStudent",
"type": "main",
"index": 0
}
],
[
{
"node": "Build Error Common",
"type": "main",
"index": 0
}
]
]
},
"Build library fields": {
"main": [
[
{
"node": "Create LibraryItem",
"type": "main",
"index": 0
}
],
[
{
"node": "Build Error Common",
"type": "main",
"index": 0
}
]
]
},
"Create LibraryItem": {
"main": [
[
{
"node": "Map library response",
"type": "main",
"index": 0
}
],
[
{
"node": "Build Error Common",
"type": "main",
"index": 0
}
]
]
},
"Map library response": {
"main": [
[
{
"node": "Respond saveLibraryItem",
"type": "main",
"index": 0
}
],
[
{
"node": "Build Error Common",
"type": "main",
"index": 0
}
]
]
},
"Build attempt fields": {
"main": [
[
{
"node": "Create QuizAttempt",
"type": "main",
"index": 0
}
],
[
{
"node": "Build Error Common",
"type": "main",
"index": 0
}
]
]
},
"Create QuizAttempt": {
"main": [
[
{
"node": "Map attempt response",
"type": "main",
"index": 0
}
],
[
{
"node": "Build Error Common",
"type": "main",
"index": 0
}
]
]
},
"Map attempt response": {
"main": [
[
{
"node": "Respond saveAttempt",
"type": "main",
"index": 0
}
],
[
{
"node": "Build Error Common",
"type": "main",
"index": 0
}
]
]
},
"Build Error Common": {
"main": [
[
{
"node": "Respond Error",
"type": "main",
"index": 0
}
]
]
},
"Build Unknown Action Error": {
"main": [
[
{
"node": "Respond Unknown Action",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"tags": []
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
sync-state. Uses airtable. Webhook trigger; 28 nodes.
Source: https://github.com/kailasnath2255/sheldon-library/blob/715eca7e90828ed74e4d6e61faaa8d1b6bc837d5/n8n/workflows/sync-state.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.
PURPOSE: Automatically send professional appointment reminders via email and SMS to reduce no-shows and improve patient experience.
Buildnbloom - Typeform to Tier 1 Call. Uses supabase, airtable, httpRequest. Webhook trigger; 17 nodes.
zaad9_teams_dane. Uses emailSend, airtable, slack, microsoftTeams. Webhook trigger; 7 nodes.
Convert Airtable Rich Text Markdown Field To Html. Uses airtable, markdown, stickyNote. Webhook trigger; 9 nodes.
BP_check. Uses googleSheets, @n-octo-n/n8n-nodes-json-database, httpRequest, itemLists. Webhook trigger; 99 nodes.