{
  "name": "Restyle your catalog for the new season on autopilot (Mar 1 + Sep 1)",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 9 1 3,9 *"
            }
          ]
        }
      },
      "id": "dcf68471-9d9b-405a-af47-47cf102dc585",
      "name": "Season Flip (Mar 1 + Sep 1)",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "authentication": "accessToken",
        "resource": "product",
        "operation": "getAll",
        "returnAll": true,
        "additionalFields": {}
      },
      "id": "f9478927-6d59-452c-a01d-130b79c1c2e8",
      "name": "Get Products",
      "type": "n8n-nodes-base.shopify",
      "typeVersion": 1,
      "position": [
        224,
        0
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": false,
            "leftValue": "",
            "typeValidation": "loose",
            "version": 1
          },
          "conditions": [
            {
              "leftValue": "={{ ($json.tags || '').split(',').map(t => t.trim()).includes('seasonal-restyle') }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "14391ec6-ca91-4d49-ae12-f9e6d5791a6c",
      "name": "Tagged seasonal-restyle?",
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2.2,
      "position": [
        448,
        0
      ]
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "text": "Seasonal catalog restyle complete.",
        "otherOptions": {}
      },
      "id": "e247031c-ac0d-4285-8c25-f9fd81f7a4d7",
      "name": "Flip Complete",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.5,
      "position": [
        912,
        -160
      ]
    },
    {
      "parameters": {
        "authentication": "apiKey",
        "talentId": "b2c80190-4a00-4718-9d3f-c531472d5984",
        "shotCodes": [
          "model_front_women"
        ],
        "frontImageUrl": "={{ $json.images[0].src }}",
        "outputFormat": "jpeg",
        "outputAspectRatio": 5,
        "callbackUrl": "={{ $execution.resumeUrl }}",
        "operation": "generateModelShots"
      },
      "id": "6b459665-96dc-4ea7-b53c-458ea3af9765",
      "name": "Generate Seasonal (Female)",
      "type": "n8n-nodes-dreem.dreem",
      "typeVersion": 1,
      "position": [
        912,
        128
      ]
    },
    {
      "parameters": {
        "resume": "webhook",
        "httpMethod": "POST",
        "limitWaitTime": true,
        "resumeAmount": 20,
        "resumeUnit": "minutes",
        "options": {}
      },
      "id": "afca8254-9b7f-4177-a540-7c636f09bcf7",
      "name": "Wait for Render",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        1120,
        128
      ]
    },
    {
      "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": "f60489e9-a8a0-457b-80f5-5a8ef90d4b0d",
      "name": "Is Complete?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1344,
        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": "3f4c9a80-d366-4435-9bbd-f70611f366c4",
      "name": "Publish to Shopify",
      "type": "n8n-nodes-base.shopify",
      "typeVersion": 1,
      "position": [
        1568,
        48
      ]
    },
    {
      "parameters": {
        "options": {}
      },
      "id": "00fe5339-3385-4201-9b61-e0806647c064",
      "name": "Loop Over Products",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        672,
        0
      ]
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "text": "=Seasonal restyle skipped *{{ $('Loop Over Products').item.json.title }}* — render didn't finish.",
        "otherOptions": {}
      },
      "id": "112728b2-a73f-4b16-8e29-61c6557aaef7",
      "name": "Skipped",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.5,
      "position": [
        1568,
        224
      ]
    },
    {
      "parameters": {
        "content": "## 🍂 Seasonal catalog restyle (Mar 1 + Sep 1)\nTwice a year - **March 1** (spring/summer) and **September 1** (autumn/winter) at 09:00 - this workflow gives every product tagged **`seasonal-restyle`** a fresh on-model shot in the new season's look. The new image is added to the product - your existing images stay.\n\nUse it to keep your product pages looking in-season all year, without booking a reshoot.\n\n### How it works\n*Get Products* pulls your catalog → the filter keeps only products tagged `seasonal-restyle` → the loop sends each product's first image to Dreem, which renders it on the model you picked → *Publish to Shopify* appends the finished shot to the product. Renders that don't finish in 20 minutes are flagged in Slack and skipped. When the whole batch is done you get a Slack ping.\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* (+ *Publish Male Shot* if enabled) · **Dreem API** (your `dreem_pk_...` key) on *Generate Seasonal (Female)* (+ *(Male)* if enabled) · **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 *Flip Complete* + *Skipped*.\n**2. Tag your products** - add the `seasonal-restyle` tag in Shopify to every product you want refreshed.\n**3. Pick the season's model + pose** on *Generate Seasonal (Female)* - see the 👤 note. Do this **before each flip** so the look matches the incoming season.\n**4. Add the season's styling items** - see the 🧥 note.\n**5. Pick your Slack channel** on both Slack nodes.\n**6. Toggle Active** (top right). It then runs by itself every Mar 1 + Sep 1.",
        "height": 860,
        "width": 560,
        "color": 7
      },
      "id": "3c1666e6-2e4e-48eb-9b51-2328a6fe848b",
      "name": "Setup — Start Here",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -96,
        -960
      ]
    },
    {
      "parameters": {
        "authentication": "apiKey",
        "talentId": "ddb6969e-5099-4337-b528-2e85888eef38",
        "shotCodes": [
          "model_hands_in_pockets_front_men"
        ],
        "frontImageUrl": "={{ $('Loop Over Products').item.json.images[0].src }}",
        "outputFormat": "jpeg",
        "outputAspectRatio": 5,
        "callbackUrl": "={{ $execution.resumeUrl }}",
        "operation": "generateModelShots"
      },
      "id": "3472f299-8985-473d-b85b-41e22ce4b5df",
      "name": "Generate Seasonal (Male)",
      "type": "n8n-nodes-dreem.dreem",
      "typeVersion": 1,
      "position": [
        912,
        464
      ],
      "disabled": true
    },
    {
      "parameters": {
        "resume": "webhook",
        "httpMethod": "POST",
        "limitWaitTime": true,
        "resumeAmount": 20,
        "resumeUnit": "minutes",
        "options": {}
      },
      "id": "3334cb15-665a-4d42-92df-cd479543d619",
      "name": "Wait Male",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        1120,
        464
      ],
      "disabled": true
    },
    {
      "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": "2d28d288-a547-4e6f-9698-e12fdcf27f0d",
      "name": "Male Done?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1344,
        464
      ],
      "disabled": true
    },
    {
      "parameters": {
        "authentication": "accessToken",
        "resource": "product",
        "operation": "update",
        "productId": "={{ $('Loop Over Products').item.json.id }}",
        "updateFields": {
          "images": "={{ ($('Publish to Shopify').item.json.images || []).map(i => ({ id: i.id })).concat(($('Wait Male').item.json.body.outputs || []).map(o => ({ src: o.files[0].url }))) }}"
        }
      },
      "id": "456ad1b1-6065-48a7-b733-775f7c6f3258",
      "name": "Publish Male Shot",
      "type": "n8n-nodes-base.shopify",
      "typeVersion": 1,
      "position": [
        1568,
        464
      ],
      "disabled": true
    },
    {
      "parameters": {
        "content": "### 🧥 Upload the season's styling items\n- **Styling Image URLs** on the Generate nodes - paste image URLs of the pieces that say \"new season\" (coat, scarf, knitwear...). Dreem dresses the model with them around your product. Easiest source: copy the image URL of another product in your own store.\n- Leave it **empty** and Dreem styles the outfit itself.",
        "height": 300,
        "width": 400,
        "color": 5
      },
      "id": "76412c8e-5d55-42b6-a8c3-544fe75ca62f",
      "name": "Note — Styling",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1392,
        656
      ]
    },
    {
      "parameters": {
        "content": "### 👤 Pick the season's model + pose\nOpen *Generate Seasonal (Female)* and set:\n- **Talent ID** - the model who wears your products this season. Browse all models at [dreem.ai](https://dreem.ai) and paste the ID here. Default: Astrid Holm.\n- **Shot Codes** - the pose. 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.\n\n⚠️ Use the **same model + pose for the whole batch** - that's what makes the refreshed catalog look coherent.",
        "height": 500,
        "width": 464,
        "color": 4
      },
      "id": "ba1d525e-c86d-4f34-b408-bb69f2da33da",
      "name": "Note — Model & Pose",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        848,
        656
      ]
    },
    {
      "parameters": {
        "content": "### 🚹 Optional - male model shot\nThe greyed-out bottom row renders a **second shot on a male model** after the female one is published. It ships **disabled**.\n\nSell menswear too? Enable the 4 nodes and pick a **male talent + male pose** on *Generate Seasonal (Male)* - browse both at [dreem.ai](https://dreem.ai). Add your Dreem + Shopify credentials there as well.",
        "height": 380,
        "width": 340,
        "color": 3
      },
      "id": "d9fb7378-96b0-4bc7-bc48-d93239bbef9f",
      "name": "Note — Male Chain",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        224,
        464
      ]
    }
  ],
  "connections": {
    "Season Flip (Mar 1 + Sep 1)": {
      "main": [
        [
          {
            "node": "Get Products",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Products": {
      "main": [
        [
          {
            "node": "Tagged seasonal-restyle?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Tagged seasonal-restyle?": {
      "main": [
        [
          {
            "node": "Loop Over Products",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for Render": {
      "main": [
        [
          {
            "node": "Is Complete?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Complete?": {
      "main": [
        [
          {
            "node": "Publish to Shopify",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Skipped",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Products": {
      "main": [
        [
          {
            "node": "Flip Complete",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Generate Seasonal (Female)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Skipped": {
      "main": [
        [
          {
            "node": "Loop Over Products",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Seasonal (Female)": {
      "main": [
        [
          {
            "node": "Wait for Render",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Publish to Shopify": {
      "main": [
        [
          {
            "node": "Generate Seasonal (Male)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Seasonal (Male)": {
      "main": [
        [
          {
            "node": "Wait Male",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait Male": {
      "main": [
        [
          {
            "node": "Male Done?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Male Done?": {
      "main": [
        [
          {
            "node": "Publish Male Shot",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Skipped",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Publish Male Shot": {
      "main": [
        [
          {
            "node": "Loop Over Products",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate"
  }
}