{
  "name": "Faceless channel factory (Schedule \u2192 render \u2192 TokPortal configure & publish)",
  "nodes": [
    {
      "parameters": {
        "content": "## Faceless channel factory\nEvery day: generate (or fetch) a rendered video URL, configure the next free slot of a **videos_only** bundle on your delivered account, and publish it.\n\nReplace the placeholder **HTTP Request** with your renderer (Creatomate, Shotstack, Sora/Veo pipeline, ...). It must return a public direct `.mp4` URL as `video_url` and a `caption`.\n\nSet `ACCOUNT_ID` and `BUNDLE_ID` in **Settings**.",
        "height": 260,
        "width": 620,
        "color": 4
      },
      "id": "tp-011",
      "name": "Sticky Notetp-010",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -40,
        -280
      ]
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 9 * * *"
            }
          ]
        }
      },
      "id": "tp-012",
      "name": "Every Day 09:00",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        60
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "s1",
              "name": "BUNDLE_ID",
              "value": "REPLACE_WITH_VIDEOS_ONLY_BUNDLE_ID",
              "type": "string"
            },
            {
              "id": "s2",
              "name": "ACCOUNT_ID",
              "value": "REPLACE_WITH_SAVED_ACCOUNT_ID",
              "type": "string"
            },
            {
              "id": "s3",
              "name": "topic",
              "value": "daily motivation quote",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "tp-013",
      "name": "Settings",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        220,
        60
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://your-renderer.example.com/render",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ { \"topic\": $json.topic, \"format\": \"9:16\", \"duration\": 30 } }}",
        "options": {}
      },
      "id": "tp-014",
      "name": "Generate Video (placeholder)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        440,
        60
      ]
    },
    {
      "parameters": {
        "resource": "bundle",
        "operation": "listVideos",
        "bundleId": "={{ $(\"Settings\").item.json.BUNDLE_ID }}"
      },
      "id": "tp-015",
      "name": "List Bundle Videos",
      "type": "n8n-nodes-tokportal.tokPortal",
      "typeVersion": 1,
      "position": [
        660,
        60
      ],
      "credentials": {
        "tokPortalApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Find the first slot that has no configuration yet.\nconst slots = $input.all().map(i => i.json);\nconst free = slots.find(s => !s.video_url && !s.description && (s.status === 'pending' || !s.status));\nif (!free) {\n  throw new Error('No free video slot left on this bundle. Add slots (POST /bundles/{id}/add-video-slots) or create a new videos_only bundle.');\n}\nconst render = $('Generate Video (placeholder)').first().json;\nreturn [{ json: {\n  position: free.position,\n  video_url: render.video_url,\n  caption: render.caption || 'Daily post #fyp',\n  target_publish_date: $now.plus({ days: 1 }).toFormat('yyyy-LL-dd'),\n} }];"
      },
      "id": "tp-016",
      "name": "Pick Next Free Slot",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        880,
        60
      ]
    },
    {
      "parameters": {
        "resource": "video",
        "operation": "configure",
        "bundleId": "={{ $(\"Settings\").item.json.BUNDLE_ID }}",
        "position": "={{ $json.position }}",
        "videoType": "video",
        "targetPublishDate": "={{ $json.target_publish_date }}",
        "videoUrl": "={{ $json.video_url }}",
        "description": "={{ $json.caption }}",
        "additionalFields": {
          "ai_content_disclaimer": true,
          "auto_publish": false
        }
      },
      "id": "tp-017",
      "name": "Configure Video Slot",
      "type": "n8n-nodes-tokportal.tokPortal",
      "typeVersion": 1,
      "position": [
        1100,
        60
      ],
      "credentials": {
        "tokPortalApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "resource": "video",
        "operation": "publish",
        "bundleId": "={{ $(\"Settings\").item.json.BUNDLE_ID }}",
        "position": "={{ $(\"Pick Next Free Slot\").item.json.position }}"
      },
      "id": "tp-018",
      "name": "Publish Video Slot",
      "type": "n8n-nodes-tokportal.tokPortal",
      "typeVersion": 1,
      "position": [
        1320,
        60
      ],
      "credentials": {
        "tokPortalApi": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Every Day 09:00": {
      "main": [
        [
          {
            "node": "Settings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Settings": {
      "main": [
        [
          {
            "node": "Generate Video (placeholder)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Video (placeholder)": {
      "main": [
        [
          {
            "node": "List Bundle Videos",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "List Bundle Videos": {
      "main": [
        [
          {
            "node": "Pick Next Free Slot",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pick Next Free Slot": {
      "main": [
        [
          {
            "node": "Configure Video Slot",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Configure Video Slot": {
      "main": [
        [
          {
            "node": "Publish Video Slot",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "tags": [
    {
      "name": "TokPortal"
    }
  ]
}