{
  "name": "FetchFox Instagram creator research starter v1",
  "nodes": [
    {
      "id": "manual-run",
      "name": "Manual run",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        240
      ],
      "parameters": {}
    },
    {
      "id": "configure-input",
      "name": "Configure input",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        240,
        240
      ],
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "profileUrl",
              "name": "profileUrl",
              "type": "string",
              "value": "https://www.instagram.com/REPLACE_USERNAME/"
            }
          ]
        },
        "options": {}
      }
    },
    {
      "id": "validate-input",
      "name": "Validate input",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        480,
        240
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const value = $('Configure input').first().json.profileUrl;\nif (typeof value !== 'string' || value.includes('REPLACE_')) throw new Error('Set profileUrl to one public Instagram profile URL.');\nconst match = /^https:\\/\\/(?:www\\.)?instagram\\.com\\/([A-Za-z0-9_.]+)\\/?(?:\\?[^\\s]*)?$/.exec(value);\nif (!match || ['p', 'reel', 'reels', 'stories', 'explore'].includes(match[1])) throw new Error('Use an HTTPS Instagram profile URL, not a post or reel.');\nreturn [{ json: { profileUrl: value } }];"
      }
    },
    {
      "id": "fetch-profile",
      "name": "Fetch profile",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        720,
        240
      ],
      "parameters": {
        "method": "GET",
        "url": "https://api.fetchfox.net/instagram/channel-stats",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "url",
              "value": "={{ $('Configure input').first().json.profileUrl }}"
            }
          ]
        },
        "options": {
          "timeout": 180000,
          "redirect": {
            "redirect": {
              "followRedirects": false
            }
          },
          "response": {
            "response": {
              "fullResponse": true,
              "neverError": false,
              "responseFormat": "json"
            }
          }
        }
      },
      "retryOnFail": false
    },
    {
      "id": "check-profile",
      "name": "Check profile",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        960,
        240
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const response = $input.first().json;\nif (response.statusCode !== 200 || response.body?.success !== true || !response.body.data) throw new Error('FetchFox did not return a successful result. Inspect the HTTP node; correct input/authentication, wait for Retry-After on 429, or check your credits before rerunning.');\nreturn [{ json: response }];"
      }
    },
    {
      "id": "fetch-posts",
      "name": "Fetch posts",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1200,
        240
      ],
      "parameters": {
        "method": "GET",
        "url": "https://api.fetchfox.net/instagram/channel-posts",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "url",
              "value": "={{ $('Configure input').first().json.profileUrl }}"
            },
            {
              "name": "limit",
              "value": "20"
            }
          ]
        },
        "options": {
          "timeout": 180000,
          "redirect": {
            "redirect": {
              "followRedirects": false
            }
          },
          "response": {
            "response": {
              "fullResponse": true,
              "neverError": false,
              "responseFormat": "json"
            }
          }
        }
      },
      "retryOnFail": false
    },
    {
      "id": "check-posts",
      "name": "Check posts",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1440,
        240
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const response = $input.first().json;\nif (response.statusCode !== 200 || response.body?.success !== true || !response.body.data) throw new Error('FetchFox did not return a successful result. Inspect the HTTP node; correct input/authentication, wait for Retry-After on 429, or check your credits before rerunning.');\nreturn [{ json: response }];"
      }
    },
    {
      "id": "fetch-reels",
      "name": "Fetch reels",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1680,
        240
      ],
      "parameters": {
        "method": "GET",
        "url": "https://api.fetchfox.net/instagram/channel-reels",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "url",
              "value": "={{ $('Configure input').first().json.profileUrl }}"
            },
            {
              "name": "limit",
              "value": "20"
            }
          ]
        },
        "options": {
          "timeout": 180000,
          "redirect": {
            "redirect": {
              "followRedirects": false
            }
          },
          "response": {
            "response": {
              "fullResponse": true,
              "neverError": false,
              "responseFormat": "json"
            }
          }
        }
      },
      "retryOnFail": false
    },
    {
      "id": "creator-report",
      "name": "Creator report",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1920,
        240
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const response = $input.first().json;\nif (response.statusCode !== 200 || response.body?.success !== true || !response.body.data) throw new Error('FetchFox did not return a successful result. Inspect the HTTP node; correct input/authentication, wait for Retry-After on 429, or check your credits before rerunning.');\n\nconst profile = $('Fetch profile').first().json.body.data;\nconst posts = $('Fetch posts').first().json.body.data;\nconst reels = response.body.data;\nif (!Array.isArray(posts.items) || !Array.isArray(reels.items)) throw new Error('Expected posts and reels arrays.');\nreturn [{ json: { sourceUrl: $('Configure input').first().json.profileUrl, retrievedAt: new Date().toISOString(), profile: { username: profile.username, name: profile.nickname, bio: profile.bio, followers: profile.followers ?? null, following: profile.following ?? null, totalPosts: profile.totalPosts ?? null, verified: profile.verified ?? null }, posts: posts.items, reels: reels.items, creditsUsed: ['Fetch profile', 'Fetch posts', 'Fetch reels'].reduce((sum, name) => sum + Number($(name).first().json.headers?.['x-credits-used'] || 0), 0) } }];"
      }
    },
    {
      "id": "setup-and-credit-cost",
      "name": "Setup and credit cost",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        240,
        240
      ],
      "parameters": {
        "content": "## FetchFox starter v1\n\n1. Edit Configure input.\n2. Create an n8n Header Auth credential: name x-access-key, value your FetchFox key. Select it in every Fetch node.\n3. Execute manually.\n\nUp to 3 credits per run: profile + up to 20 posts + up to 20 reels. Each successful request costs 1 credit, including cache hits. Stops on the first failed request.\n\nNo schedules or automatic retries. No credentials are included. Keep keys in n8n credentials. Source data can be partial or cached.",
        "width": 540,
        "height": 280
      }
    }
  ],
  "connections": {
    "Manual run": {
      "main": [
        [
          {
            "node": "Configure input",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Configure input": {
      "main": [
        [
          {
            "node": "Validate input",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate input": {
      "main": [
        [
          {
            "node": "Fetch profile",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch profile": {
      "main": [
        [
          {
            "node": "Check profile",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check profile": {
      "main": [
        [
          {
            "node": "Fetch posts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch posts": {
      "main": [
        [
          {
            "node": "Check posts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check posts": {
      "main": [
        [
          {
            "node": "Fetch reels",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch reels": {
      "main": [
        [
          {
            "node": "Creator report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "executionTimeout": 600,
    "timezone": "UTC",
    "saveDataSuccessExecution": "none",
    "saveDataErrorExecution": "none",
    "saveManualExecutions": false
  },
  "pinData": {},
  "tags": []
}
