{ "id": "TApiWf38Vetting01", "name": "Influencer Vetting Pipeline (TranscriptAPI)", "nodes": [ { "parameters": {}, "id": "38383838-3838-4838-8838-383838383801", "name": "Start", "type": "n8n-nodes-base.manualTrigger", "typeVersion": 1, "position": [ -320, 0 ] }, { "parameters": { "assignments": { "assignments": [ { "id": "38383838-3838-4838-8838-3838383838a1", "name": "channel", "value": "REPLACE_WITH_INFLUENCER_CHANNEL_HANDLE_OR_ID", "type": "string" } ] }, "options": {} }, "id": "38383838-3838-4838-8838-383838383802", "name": "Set Channel", "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [ -100, 0 ] }, { "parameters": { "url": "https://transcriptapi.com/api/v2/youtube/channel/resolve", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "sendQuery": true, "queryParameters": { "parameters": [ { "name": "input", "value": "={{ $json.channel }}" } ] }, "options": {} }, "id": "38383838-3838-4838-8838-383838383803", "name": "Resolve Channel", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 120, 0 ], "credentials": { "httpHeaderAuth": { "id": "REPLACE_TRANSCRIPTAPI_CRED_ID", "name": "TranscriptAPI - Authorization Bearer" } } }, { "parameters": { "url": "https://transcriptapi.com/api/v2/youtube/channel/videos", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "sendQuery": true, "queryParameters": { "parameters": [ { "name": "channel", "value": "={{ $json.channel_id }}" } ] }, "options": {} }, "id": "38383838-3838-4838-8838-383838383804", "name": "List Channel Videos", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 340, 0 ], "credentials": { "httpHeaderAuth": { "id": "REPLACE_TRANSCRIPTAPI_CRED_ID", "name": "TranscriptAPI - Authorization Bearer" } } }, { "parameters": { "jsCode": "const data = $input.first().json;\nreturn (data.results || []).map((v) => ({ json: { videoId: v.videoId, videoTitle: v.title || null, videoUrl: 'https://www.youtube.com/watch?v=' + v.videoId } }));" }, "id": "38383838-3838-4838-8838-383838383805", "name": "Extract Sample", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 560, 0 ] }, { "parameters": { "maxItems": 3 }, "id": "38383838-3838-4838-8838-383838383806", "name": "Keep First 3", "type": "n8n-nodes-base.limit", "typeVersion": 1, "position": [ 780, 0 ] }, { "parameters": { "url": "https://transcriptapi.com/api/v2/youtube/transcript", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "sendQuery": true, "queryParameters": { "parameters": [ { "name": "video_url", "value": "={{ $json.videoUrl }}" }, { "name": "format", "value": "json" }, { "name": "send_metadata", "value": "true" } ] }, "options": {} }, "id": "38383838-3838-4838-8838-383838383807", "name": "Get Transcript (TranscriptAPI)", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1000, 0 ], "credentials": { "httpHeaderAuth": { "id": "REPLACE_TRANSCRIPTAPI_CRED_ID", "name": "TranscriptAPI - Authorization Bearer" } }, "onError": "continueRegularOutput" }, { "parameters": { "jsCode": "const MAX = 4000; const titles = []; const blocks = [];\nfor (const item of $input.all()) {\n const d = item.json; const seg = Array.isArray(d.transcript) ? d.transcript : [];\n const meta = d.metadata || {}; const vid = d.video_id; const title = meta.title || vid;\n titles.push(title);\n if (seg.length > 0) blocks.push('### ' + title + '\\n' + seg.map((s) => s.text).join(' ').slice(0, MAX));\n}\nreturn [\n {\n json: {\n channel: $('Set Channel').first().json.channel,\n channelId: $('Resolve Channel').first().json.channel_id,\n sampledTitles: titles,\n combinedText: blocks.join('\\n\\n'),\n },\n },\n];" }, "id": "38383838-3838-4838-8838-383838383808", "name": "Collect Vetting Input", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1220, 0 ] }, { "parameters": { "method": "POST", "url": "https://api.openai.com/v1/chat/completions", "authentication": "genericCredentialType", "genericAuthType": "httpHeaderAuth", "sendBody": true, "specifyBody": "json", "jsonBody": "={{ JSON.stringify({ model: 'gpt-4o-mini', response_format: { type: 'json_object' }, messages: [ { role: 'system', content: 'You are a brand-safety and influencer-fit analyst. Given sampled video transcripts from a creator, assess brand suitability. Respond ONLY with a JSON object with keys: overall_fit_score (0-100), brand_safety (one of safe, caution, unsafe), flags (array from: profanity, controversy, misinformation, adult, political, none), rationale (2-3 sentences), recommended (boolean). Base it only on the transcripts.' }, { role: 'user', content: 'Creator: ' + $json.channel + '\\n\\nSampled transcripts:\\n' + $json.combinedText } ] }) }}", "options": {} }, "id": "38383838-3838-4838-8838-383838383809", "name": "Score Brand Safety (LLM)", "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 1440, 0 ], "credentials": { "httpHeaderAuth": { "id": "REPLACE_OPENAI_CRED_ID", "name": "OpenAI - Authorization Bearer" } } }, { "parameters": { "jsCode": "const raw = ($json.choices && $json.choices[0] && $json.choices[0].message.content) || '';\nlet r; try { r = JSON.parse(raw); } catch (e) { r = {}; }\nconst src = $('Collect Vetting Input').first().json;\nreturn [\n {\n json: {\n channel: src.channel,\n channelId: src.channelId,\n fitScore: (typeof r.overall_fit_score === 'number' ? r.overall_fit_score : null),\n brandSafety: r.brand_safety || null,\n flags: r.flags || [],\n rationale: r.rationale || null,\n recommended: r.recommended === true,\n sampledVideos: src.sampledTitles,\n },\n },\n];" }, "id": "38383838-3838-4838-8838-383838383810", "name": "Format Vetting Row", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1660, 0 ] } ], "connections": { "Start": { "main": [ [ { "node": "Set Channel", "type": "main", "index": 0 } ] ] }, "Set Channel": { "main": [ [ { "node": "Resolve Channel", "type": "main", "index": 0 } ] ] }, "Resolve Channel": { "main": [ [ { "node": "List Channel Videos", "type": "main", "index": 0 } ] ] }, "List Channel Videos": { "main": [ [ { "node": "Extract Sample", "type": "main", "index": 0 } ] ] }, "Extract Sample": { "main": [ [ { "node": "Keep First 3", "type": "main", "index": 0 } ] ] }, "Keep First 3": { "main": [ [ { "node": "Get Transcript (TranscriptAPI)", "type": "main", "index": 0 } ] ] }, "Get Transcript (TranscriptAPI)": { "main": [ [ { "node": "Collect Vetting Input", "type": "main", "index": 0 } ] ] }, "Collect Vetting Input": { "main": [ [ { "node": "Score Brand Safety (LLM)", "type": "main", "index": 0 } ] ] }, "Score Brand Safety (LLM)": { "main": [ [ { "node": "Format Vetting Row", "type": "main", "index": 0 } ] ] } }, "active": false, "settings": { "executionOrder": "v1" }, "pinData": {} }