{
  "name": "CatalogTrace — PDF catalog lines with source coordinates (manual review)",
  "nodes": [
    {
      "parameters": {},
      "id": "ct-manual",
      "name": "Start manually",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        240
      ]
    },
    {
      "parameters": {
        "jsCode": "// Historical public example, NOT current prices. Replace URL/pages/columns for your authorized PDF.\nreturn [{ json: {\n  \"pdfUrl\": \"https://steelindustries.s3.ap-southeast-1.amazonaws.com/price-lists/SteelIndustriesMay2025Catalogue.pdf\",\n  \"options\": {\n    \"pages\": [\n      13\n    ],\n    \"decimalSeparator\": \".\",\n    \"columns\": [\n      {\n        \"name\": \"sku\",\n        \"start\": 0.105\n      },\n      {\n        \"name\": \"description\",\n        \"start\": 0.175\n      },\n      {\n        \"name\": \"length_available\",\n        \"start\": 0.35\n      },\n      {\n        \"name\": \"lengths_per_sling\",\n        \"start\": 0.465\n      },\n      {\n        \"name\": \"cut_category\",\n        \"start\": 0.545\n      },\n      {\n        \"name\": \"kina_per_tonne\",\n        \"start\": 0.6\n      },\n      {\n        \"name\": \"price\",\n        \"start\": 0.685\n      },\n      {\n        \"name\": \"kg_per_metre\",\n        \"start\": 0.77\n      },\n      {\n        \"name\": \"metres_per_tonne\",\n        \"start\": 0.85\n      }\n    ]\n  }\n} }];"
      },
      "id": "ct-input",
      "name": "Choose PDF and layout",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        240,
        240
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.apify.com/v2/actors/xGfGSzXzOIH13TAA9/run-sync-get-dataset-items",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "memory",
              "value": "512"
            },
            {
              "name": "timeout",
              "value": "60"
            },
            {
              "name": "maxTotalChargeUsd",
              "value": "0.11"
            },
            {
              "name": "format",
              "value": "json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify($json) }}",
        "options": {
          "timeout": 90000,
          "response": {
            "response": {
              "responseFormat": "json"
            }
          },
          "redirect": {
            "redirect": {
              "followRedirects": false
            }
          }
        }
      },
      "id": "ct-extract",
      "name": "Extract with CatalogTrace",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        480,
        240
      ],
      "retryOnFail": false
    },
    {
      "parameters": {
        "jsCode": "const incoming = $input.all();\nconst rows = incoming.flatMap(item => Array.isArray(item.json) ? item.json : [item.json]);\nif (!rows.length) throw new Error('No rows received. Inspect the Apify run before retrying.');\nif (rows.length > 1000) throw new Error('Unexpected row count. Stop and inspect the run.');\nreturn rows.map(row => {\n  if (!row || typeof row.raw_text !== 'string' || !Number.isInteger(row.page) || row.page < 1 || !row.source || !Array.isArray(row.source.bbox) || row.source.bbox.length !== 4 || row.source.bbox.some(n => typeof n !== 'number' || !Number.isFinite(n)) || row.review_required !== true) {\n    throw new Error('Unexpected CatalogTrace response. Stop; do not import it.');\n  }\n  return { json: { ...row, review_required: true, approval_status: 'pending_human_review', approved_for_import: false } };\n});"
      },
      "id": "ct-review",
      "name": "Human review queue",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        720,
        240
      ]
    },
    {
      "parameters": {
        "content": "# Setup before execution\n1. Read https://catalogtrace-kiza.pages.dev/n8n.html\n2. Select your own Header Auth credential on the HTTP node (Authorization: Bearer YOUR_APIFY_TOKEN). No credentials included.\n3. Check PDF URL, layout and current Apify pricing.\n4. Each manual run may be charged. Budget $0.11 per run, 512 MB, 60 s Actor timeout. No automatic retries.\n5. Stop at human review. No email, ERP or spreadsheet writes.\n\nIndependently authored starter. Local checks only; not yet imported/executed in n8n or approved by n8n. Historical catalog example, not a customer case.",
        "height": 340,
        "width": 900
      },
      "id": "ct-note",
      "name": "Read first",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -20,
        -180
      ]
    }
  ],
  "connections": {
    "Start manually": {
      "main": [
        [
          {
            "node": "Choose PDF and layout",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Choose PDF and layout": {
      "main": [
        [
          {
            "node": "Extract with CatalogTrace",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract with CatalogTrace": {
      "main": [
        [
          {
            "node": "Human review queue",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {},
  "tags": []
}
