{
  "name": "FLUF + Airtable \u2014 listing error tasks",
  "nodes": [
    {
      "id": "bf1f15d1-d180-5d3b-b620-1e220f678343",
      "name": "Overview",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -660,
        -440
      ],
      "parameters": {
        "content": "## Track FLUF marketplace listing errors in Airtable\n\n### How it works\nWhen a marketplace rejects a listing during crosslisting, FLUF sends the error to this workflow, which adds a Listing error task to your Tasks table with the marketplace and the reason. Tasks are upserted by event ID, so retries never create duplicates.\n\n### Setup\n1. Copy the Airtable template (link below) or use your own base with the same field names.\n2. Open **Configure workspace** and paste your base ID and the Inventory, Sales and Tasks table IDs.\n3. Select your Airtable personal access token credential on every Airtable request node.\n4. On FLUF HTTP request nodes use Header Auth: `Authorization` = `Bearer YOUR_FLUF_PAT`.\n5. Select your FLUF Connect API credential on each FLUF trigger.\n6. In FLUF, choose n8n as the automation owner for this base (one owner per base).\n7. Test with zero-stock drafts first, then activate.\n\n### Requirements\nYour own n8n workspace, an Airtable base and a paid FLUF plan with API write access (not included in the trial).\n\nTemplate base: https://airtable.com/appGvPOBL2b7Lfxwg/shryPFF1iDosEzitJ\nGuide: https://fluf.io/support/connect-airtable/",
        "height": 1000,
        "width": 560,
        "color": 4
      }
    },
    {
      "id": "cae1933a-2ea4-5ffe-b407-170cb04e6189",
      "name": "Note 1",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -60,
        -260
      ],
      "parameters": {
        "content": "## 1. Error received\nThe FLUF Connect trigger fires on each crosslisting error. **Configure workspace** holds your base and table IDs.",
        "height": 420,
        "width": 520,
        "color": 7
      }
    },
    {
      "id": "6352cfa1-9fe2-579e-bd80-64aece532ba0",
      "name": "Note 2",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        540,
        -260
      ],
      "parameters": {
        "content": "## 2. Create the review task\nUpserts a Tasks row: Task key, FLUF ID, Type = Listing error, Marketplace, Details (the error message) and Created at.\nAirtable and FLUF requests make up to three attempts in total, waiting 35 seconds after a rate limit (429) or server error. Other errors stop the run so you can see them in the execution.",
        "height": 620,
        "width": 940,
        "color": 7
      }
    },
    {
      "id": "f805af14-6f2b-583c-9ad5-2848b3db3dea",
      "name": "Crosslisting error",
      "type": "n8n-nodes-fluf-connect.flufConnectTrigger",
      "typeVersion": 1,
      "position": [
        0,
        0
      ],
      "parameters": {
        "event": "crosslisting_error"
      },
      "webhookId": "d755e798-abc4-5235-8344-d61f2565b424"
    },
    {
      "id": "8a4d53f4-dff9-5df9-8ac3-212e52f75dbe",
      "name": "Configure workspace",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        300,
        0
      ],
      "parameters": {
        "jsCode": "// Choose a base and its four FLUF tables. Use standard field names from the guide.\nconst config = { baseId: 'REPLACE_BASE_ID', inventory: 'REPLACE_INVENTORY_TABLE_ID', sales: 'REPLACE_SALES_TABLE_ID', tasks: 'REPLACE_TASKS_TABLE_ID', allowPublish: false };\nif (!/^app[A-Za-z0-9]+$/.test(config.baseId)) throw new Error('Set your Airtable base ID in Configure workspace.');\nfor (const key of ['inventory','sales','tasks']) if (!/^tbl[A-Za-z0-9]+$/.test(config[key])) throw new Error('Set the '+key+' table ID.');\nreturn $input.all().map((item,i)=>({json:{...item.json,config},pairedItem:{item:i}}));"
      }
    },
    {
      "id": "1490081d-b312-5a47-8b8c-72ea35027025",
      "name": "Request Create listing review task",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        840,
        0
      ],
      "parameters": {
        "method": "PATCH",
        "url": "={{ 'https://api.airtable.com/v0/'+$json.config.baseId+'/'+$json.config.tasks }}",
        "authentication": "predefinedCredentialType",
        "options": {
          "batching": {
            "batch": {
              "batchSize": 1,
              "batchInterval": 350
            }
          },
          "response": {
            "response": {
              "fullResponse": true,
              "neverError": true
            }
          }
        },
        "nodeCredentialType": "airtableTokenApi",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ {performUpsert:{fieldsToMergeOn:['Task key']},records:[{fields:{'Task key':$json.event_id,'FLUF ID':String($json.listing_id||''),'Type':'Listing error','Marketplace':$json.channel||'','Details':$json.error_message||$json.message||'Review the listing error in FLUF.','Created at':$json.occurred_at||$json.fired_at||''} }]} }}"
      },
      "retryOnFail": false,
      "onError": "continueRegularOutput"
    },
    {
      "id": "f33e80d9-bb14-5346-9948-4eee42180b30",
      "name": "Attempt Create listing review task",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        600,
        0
      ],
      "parameters": {
        "jsCode": "return $input.all().map((item,i)=>({json:{...item.json,__airtableAttempt:Number(item.json.__airtableAttempt||0)+1},pairedItem:{item:i}}));"
      }
    },
    {
      "id": "b293996c-effe-5480-bbe5-3c65d8dccf3f",
      "name": "Create listing review task",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1080,
        0
      ],
      "parameters": {
        "jsCode": "return $input.all().map((item,i)=>{\n const before=$(\"Attempt Create listing review task\").itemMatching(i).json, response=item.json;\n const status=Number(response.statusCode||0);\n if(status>=200 && status<300) return {json:{...response.body,__airtableRetry:false},pairedItem:{item:i}};\n if((status===0||status===429||status>=500) && before.__airtableAttempt<3) return {json:{...before,__airtableRetry:true},pairedItem:{item:i}};\n const error=response.body?.message||response.body?.error?.message||'The request failed. Check the connection, field mapping and service allowance.';\n if(!false) throw new Error(String(error));\n return {json:{error:String(error),__airtableRetry:false},pairedItem:{item:i}};\n});"
      }
    },
    {
      "id": "29bd3e87-fbc9-5e7b-a48d-cd42b19bf069",
      "name": "Retry Create listing review task",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1320,
        0
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "retry",
              "leftValue": "={{ $json.__airtableRetry }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "039ff210-7584-58f7-a351-d0a7a5654b6f",
      "name": "Wait for Create listing review task",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        1320,
        200
      ],
      "parameters": {
        "amount": 35,
        "unit": "seconds"
      },
      "webhookId": "f79c1e8f-fba7-510b-9494-d71e54b30139"
    }
  ],
  "connections": {
    "Crosslisting error": {
      "main": [
        [
          {
            "node": "Configure workspace",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Configure workspace": {
      "main": [
        [
          {
            "node": "Attempt Create listing review task",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Attempt Create listing review task": {
      "main": [
        [
          {
            "node": "Request Create listing review task",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Request Create listing review task": {
      "main": [
        [
          {
            "node": "Create listing review task",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create listing review task": {
      "main": [
        [
          {
            "node": "Retry Create listing review task",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for Create listing review task": {
      "main": [
        [
          {
            "node": "Attempt Create listing review task",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Retry Create listing review task": {
      "main": [
        [
          {
            "node": "Wait for Create listing review task",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "executionTimeout": 300
  },
  "tags": []
}
