{
  "name": "Rescue one-photo product pages with multi-angle model shots (weekly)",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 9 * * 1"
            }
          ]
        }
      },
      "id": "4d280d71-c263-4abb-b382-e4dc6408389f",
      "name": "Weekly Audit",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "authentication": "accessToken",
        "resource": "product",
        "operation": "getAll",
        "returnAll": true,
        "additionalFields": {}
      },
      "id": "dcec71f9-4229-47ce-a210-552050019d15",
      "name": "Get Products",
      "type": "n8n-nodes-base.shopify",
      "typeVersion": 1,
      "position": [
        224,
        0
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "leftValue": "={{ ($json.images || []).length }}",
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "rightValue": 1,
              "id": "a2d38840-b05a-4441-a00b-b5035b8b7419"
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "ab367b4e-5df1-4ebc-8b22-0afc3c2f2821",
      "name": "Only 1 Image?",
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2.2,
      "position": [
        448,
        0
      ]
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "text": "Single-image audit done - every product with only 1 image was processed. Any skipped items were flagged in this channel during the run.",
        "otherOptions": {}
      },
      "id": "d81a6a42-5c73-4a19-bea6-d6185244cf30",
      "name": "Audit Complete",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.5,
      "position": [
        912,
        -160
      ]
    },
    {
      "parameters": {
        "options": {}
      },
      "id": "e4476142-8828-4253-8f45-86f757edd048",
      "name": "Loop Over Products",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        672,
        0
      ]
    },
    {
      "parameters": {
        "content": "## 🖼️ Products with only 1 image → multi-angle model shots\nRuns every **Monday at 09:00**. It scans your catalog, finds every product with **only 1 image**, and generates a **multi-angle on-model set** from that single photo. The new shots are added to the product - your original image stays.\n\nLoop-safe: once the shots are added the product has more than 1 image, so it won't be processed again.\n\n### Setup (5 minutes)\n**1. Create + connect your credentials** (Settings → Credentials) - **Shopify Access Token API** (shop domain + Admin token, `read_products` + `write_products`) on *Get Products* + *Publish to Shopify* · **Dreem API** (your `dreem_pk_...` key) on *Generate On-Model Shots* · **Slack OAuth2** (on n8n Cloud just press *Connect*; or a *Slack API* bot token — then switch each Slack node's **Authentication** to *Access Token*) on *Audit Complete* + *Skipped*.\n**2. Pick your model + poses** on *Generate On-Model Shots* - see the note next to it.\n**3. Pick your Slack channel** on both Slack nodes, so run updates land where your team looks.\n**4. Toggle Active** (top right). From next Monday it runs on its own.",
        "height": 620,
        "width": 480,
        "color": 7
      },
      "id": "147ab815-6ab5-4660-89bf-9c2db6c0c62a",
      "name": "Setup — Start Here",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -64,
        -672
      ]
    },
    {
      "parameters": {
        "content": "### 🧥 Optional - styling\n- **Styling Image URLs** on *Generate On-Model Shots*: add image URLs of other garments to build a full look around your product.\n- Leave it **empty** and Dreem styles the outfit itself.",
        "height": 220,
        "width": 340,
        "color": 5
      },
      "id": "994ce4d9-3f2e-4d4d-912d-e8bb142eb209",
      "name": "Note — Styling",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1392,
        448
      ]
    },
    {
      "parameters": {
        "authentication": "apiKey",
        "talentId": "b2c80190-4a00-4718-9d3f-c531472d5984",
        "shotCodes": [
          "model_front_women",
          "model_hand_on_hip_front"
        ],
        "frontImageUrl": "={{ $json.images[0].src }}",
        "outputFormat": "jpeg",
        "outputAspectRatio": 5,
        "callbackUrl": "={{ $execution.resumeUrl }}",
        "operation": "generateModelShots"
      },
      "id": "150e02fe-a8d4-4790-a49e-a139748433ff",
      "name": "Generate On-Model Shots",
      "type": "n8n-nodes-dreem.dreem",
      "typeVersion": 1,
      "position": [
        912,
        128
      ]
    },
    {
      "parameters": {
        "authentication": "accessToken",
        "resource": "product",
        "operation": "update",
        "productId": "={{ $('Loop Over Products').item.json.id }}",
        "updateFields": {
          "images": "={{ ($('Loop Over Products').item.json.images || []).map(i => ({ id: i.id })).concat(($('Wait for Render').item.json.body.outputs || []).map(o => ({ src: o.files[0].url }))) }}"
        }
      },
      "id": "ab0a4300-ce7d-416f-8404-5be35adfdb71",
      "name": "Publish to Shopify",
      "type": "n8n-nodes-base.shopify",
      "typeVersion": 1,
      "position": [
        1568,
        48
      ]
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "text": "=Skipped *{{ $('Loop Over Products').item.json.title }}* - the render didn't finish (timed out or failed). The product still has only 1 image, so it will be retried next Monday.",
        "otherOptions": {}
      },
      "id": "751bbd6b-d7cb-4f39-bf32-6cb8f922a6f5",
      "name": "Skipped",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.5,
      "position": [
        1568,
        224
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose",
            "version": 1
          },
          "conditions": [
            {
              "leftValue": "={{ $json.body?.status ?? $json.status }}",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "rightValue": "completed"
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "e9c768e6-1f8b-4afd-9b55-85c4d875d2a7",
      "name": "Is Complete?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1344,
        128
      ]
    },
    {
      "parameters": {
        "resume": "webhook",
        "httpMethod": "POST",
        "limitWaitTime": true,
        "resumeAmount": 20,
        "resumeUnit": "minutes",
        "options": {}
      },
      "id": "489af179-3688-4b74-80c0-fbb2142115e6",
      "name": "Wait for Render",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        1120,
        128
      ]
    },
    {
      "parameters": {
        "content": "### 👤 Pick your model + poses\nOpen *Generate On-Model Shots* and set:\n- **Talent ID** - the model who wears your product. Browse all models at [dreem.ai](https://dreem.ai) and paste the ID here. Default: Astrid Holm.\n- **Shot Codes** - the angles you want. Add 2-3 for a real multi-angle set. Codes are gender-specific and must match your model. Browse poses at [dreem.ai](https://dreem.ai) \n- **Output Aspect Ratio** - the image format. Change it if your store uses a different shape.",
        "height": 476,
        "width": 464,
        "color": 4
      },
      "id": "d35e4bfb-cb9d-4fab-8c9b-d68b03da4cd8",
      "name": "Note — Model & Poses",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        848,
        432
      ]
    }
  ],
  "connections": {
    "Weekly Audit": {
      "main": [
        [
          {
            "node": "Get Products",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Products": {
      "main": [
        [
          {
            "node": "Only 1 Image?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Only 1 Image?": {
      "main": [
        [
          {
            "node": "Loop Over Products",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Products": {
      "main": [
        [
          {
            "node": "Audit Complete",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Generate On-Model Shots",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Skipped": {
      "main": [
        [
          {
            "node": "Loop Over Products",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Complete?": {
      "main": [
        [
          {
            "node": "Publish to Shopify",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Skipped",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for Render": {
      "main": [
        [
          {
            "node": "Is Complete?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate On-Model Shots": {
      "main": [
        [
          {
            "node": "Wait for Render",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Publish to Shopify": {
      "main": [
        [
          {
            "node": "Loop Over Products",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate"
  }
}