{
  "id": "uzqKN0BX4btt4XqD",
  "name": "Generate studio and on-model product photos for new Shopify products with Dreem.ai",
  "tags": [],
  "nodes": [
    {
      "id": "6c63dc56-497b-424a-8e25-c7d291544f37",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -192,
        0
      ],
      "parameters": {
        "width": 480,
        "height": 896,
        "content": "## Generate studio and on-model product photos for new Shopify products with Dreem.ai\n\n### How it works\n\nThis workflow watches Shopify for newly created products, verifies that the product has a source image, and uses Dreem.ai to generate front-facing studio shots and on-model photos. Completed images are sent to Slack for human approval, then approved assets are published back to Shopify. After the first publish, it generates and publishes back-view shots, while timeout branches notify Slack if an image-generation job does not finish.\n\n### Setup steps\n\n- Connect Shopify credentials for both the new product trigger and the Shopify publishing nodes, and confirm the workflow has permission to read products and upload product images.\n- Configure Dreem.ai credentials and set the prompts/templates for front shots, on-model images, and back shots.\n- Connect Slack credentials, choose the channels for image review and timeout alerts, and configure the approval interaction expected by the approval check.\n- Review the wait durations and IF conditions so they match Dreem job completion responses and your acceptable timeout window.\n\n### Customization\n\nAdjust the Dreem poses and talents, number of generated images, Slack approval channel, timeout durations, and Shopify image placement rules to match your brand workflow."
      },
      "typeVersion": 1
    },
    {
      "id": "47bce25c-731c-477f-a5f5-25ddbaee1dfe",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        400,
        464
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 320,
        "content": "## Detect image-ready product\n\nStarts when a new Shopify product is created and checks that it has an image available before generating any AI product photography."
      },
      "typeVersion": 1
    },
    {
      "id": "6e17b7c0-151a-4c1d-bc29-919d98ff0b8f",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        928,
        480
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 304,
        "content": "## Generate front shots\n\nUses Dreem AI to create front-facing studio product shots, waits for the generation job, and checks whether the output completed successfully."
      },
      "typeVersion": 1
    },
    {
      "id": "911d633d-ed28-4a40-8982-f3e93d738a02",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1632,
        496
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 304,
        "content": "## Generate model shots\n\nCreates on-model imagery from the approved product-shot stage, waits for Dreem AI to finish, and branches based on completion status."
      },
      "typeVersion": 1
    },
    {
      "id": "467d7d2f-83c0-4c80-b29d-2e9026308477",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2128,
        -96
      ],
      "parameters": {
        "color": 7,
        "width": 880,
        "height": 480,
        "content": "## Review and publish\n\nPosts generated images to Slack for review, collects an approval decision, and publishes the approved front and on-model images back to Shopify."
      },
      "typeVersion": 1
    },
    {
      "id": "00f5c641-8a81-4e05-bc42-e565d7473070",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2800,
        800
      ],
      "parameters": {
        "color": 7,
        "width": 864,
        "height": 304,
        "content": "## Generate back shots\n\nAfter the main images are published, this lower-right cluster generates back-view product shots, waits for completion, validates the result, and publishes the back shots to Shopify."
      },
      "typeVersion": 1
    },
    {
      "id": "16dfce05-306f-46bf-a1a0-558be376ca5a",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2352,
        608
      ],
      "parameters": {
        "color": 7,
        "height": 368,
        "content": "## Timeout notifications\n\nSends a Slack alert when any of the Dreem AI generation checks determines that the corresponding job did not complete in time."
      },
      "typeVersion": 1
    },
    {
      "id": "29ee2158-dcce-4868-b604-06491c216043",
      "name": "When New Shopify Product Added",
      "type": "n8n-nodes-base.shopifyTrigger",
      "position": [
        448,
        656
      ],
      "parameters": {
        "topic": "products/create",
        "authentication": "accessToken"
      },
      "typeVersion": 1
    },
    {
      "id": "32908423-6688-4ee3-b87e-0747203b1999",
      "name": "Create Front Product Images",
      "type": "n8n-nodes-dreem.dreem",
      "position": [
        976,
        640
      ],
      "parameters": {
        "operation": "generateProductShots",
        "shotCodes": [
          "flat_lay_front",
          "invisible_mannequin_front"
        ],
        "callbackUrl": "={{ $execution.resumeUrl }}",
        "backImageUrl": "={{ $json.images?.[1]?.src ?? '' }}",
        "outputFormat": "jpeg",
        "frontImageUrl": "={{ $json.images[0].src }}",
        "authentication": "apiKey",
        "outputAspectRatio": 5
      },
      "typeVersion": 1
    },
    {
      "id": "a31985bb-868b-4c37-bf6c-f9d87d610809",
      "name": "Wait for Product Images",
      "type": "n8n-nodes-base.wait",
      "position": [
        1200,
        640
      ],
      "parameters": {
        "resume": "webhook",
        "options": {},
        "httpMethod": "POST",
        "resumeUnit": "minutes",
        "resumeAmount": 20,
        "limitWaitTime": true
      },
      "typeVersion": 1.1
    },
    {
      "id": "55d18e16-87dc-4187-bd22-11483c66e950",
      "name": "Check Product Image Status",
      "type": "n8n-nodes-base.if",
      "position": [
        1424,
        640
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.body?.status ?? $json.status }}",
              "rightValue": "completed"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "b73f7a63-2e06-4584-8799-bc0cdb4b57d0",
      "name": "Create On-Model Images",
      "type": "n8n-nodes-dreem.dreem",
      "position": [
        1680,
        656
      ],
      "parameters": {
        "talentId": "b2c80190-4a00-4718-9d3f-c531472d5984",
        "shotCodes": [
          "model_front_women"
        ],
        "callbackUrl": "={{ $execution.resumeUrl }}",
        "backImageUrl": "={{ $('When New Shopify Product Added').first().json.images?.[1]?.src ?? '' }}",
        "outputFormat": "jpeg",
        "frontImageUrl": "={{ $('Wait for Product Images').first().json.body.outputs[0].files[0].url }}",
        "authentication": "apiKey",
        "outputAspectRatio": 5
      },
      "typeVersion": 1
    },
    {
      "id": "c8a80834-5319-4a51-8fb7-368cae0ff16e",
      "name": "Wait for Model Images",
      "type": "n8n-nodes-base.wait",
      "position": [
        1904,
        656
      ],
      "parameters": {
        "resume": "webhook",
        "options": {},
        "httpMethod": "POST",
        "resumeUnit": "minutes",
        "resumeAmount": 20,
        "limitWaitTime": true
      },
      "typeVersion": 1.1
    },
    {
      "id": "7ef6a28b-7e44-4922-b60d-fd47d1098959",
      "name": "Check Model Image Status",
      "type": "n8n-nodes-base.if",
      "position": [
        2128,
        656
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.body?.status ?? $json.status }}",
              "rightValue": "completed"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "57feb5a4-1654-4b37-8215-503eeaf6b8d2",
      "name": "Publish Product to Shopify",
      "type": "n8n-nodes-base.shopify",
      "position": [
        2864,
        240
      ],
      "parameters": {
        "resource": "product",
        "operation": "update",
        "productId": "={{ $('When New Shopify Product Added').first().json.id }}",
        "updateFields": {
          "images": "={{ ($('When New Shopify Product Added').first().json.images || []).map(i => ({ id: i.id })).concat(($('Wait for Product Images').first().json.body.outputs || []).map(o => ({ src: o.files[0].url }))).concat(($('Wait for Model Images').first().json.body.outputs || []).map(o => ({ src: o.files[0].url }))) }}"
        },
        "authentication": "accessToken"
      },
      "typeVersion": 1
    },
    {
      "id": "021d9616-eb87-46d6-861f-9da1acb650c3",
      "name": "Notify on Timeout",
      "type": "n8n-nodes-base.slack",
      "disabled": true,
      "position": [
        2400,
        864
      ],
      "parameters": {
        "text": "=\u26a0\ufe0f Dreem render timed out for *{{ $('When New Shopify Product Added').first().json.title }}*. Nothing was published. Check the Dreem dashboard and retry.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.5
    },
    {
      "id": "32941a06-45f5-4bb3-b5bd-3d909db63854",
      "name": "Create Back Product Images",
      "type": "n8n-nodes-dreem.dreem",
      "disabled": true,
      "position": [
        2848,
        960
      ],
      "parameters": {
        "operation": "generateProductShots",
        "shotCodes": [
          "flat_lay_back",
          "invisible_mannequin_back"
        ],
        "callbackUrl": "={{ $execution.resumeUrl }}",
        "backImageUrl": "={{ $('When New Shopify Product Added').first().json.images?.[1]?.src ?? '' }}",
        "outputFormat": "jpeg",
        "frontImageUrl": "={{ $('When New Shopify Product Added').first().json.images[0].src }}",
        "authentication": "apiKey",
        "outputAspectRatio": 5
      },
      "typeVersion": 1
    },
    {
      "id": "88d7f8ea-dd87-4ad9-9558-f81fa5a6a251",
      "name": "Wait for Back Images",
      "type": "n8n-nodes-base.wait",
      "disabled": true,
      "position": [
        3072,
        960
      ],
      "parameters": {
        "resume": "webhook",
        "options": {},
        "httpMethod": "POST",
        "resumeUnit": "minutes",
        "resumeAmount": 20,
        "limitWaitTime": true
      },
      "typeVersion": 1.1
    },
    {
      "id": "ead8746d-3962-4e46-9b80-361493d611f9",
      "name": "Check Back Image Status",
      "type": "n8n-nodes-base.if",
      "disabled": true,
      "position": [
        3296,
        960
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.body?.status ?? $json.status }}",
              "rightValue": "completed"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "69518d6c-630e-4c9a-b69b-6a3c572d2d71",
      "name": "Publish Back Images to Shopify",
      "type": "n8n-nodes-base.shopify",
      "disabled": true,
      "position": [
        3520,
        960
      ],
      "parameters": {
        "resource": "product",
        "operation": "update",
        "productId": "={{ $('When New Shopify Product Added').first().json.id }}",
        "updateFields": {
          "images": "={{ ($('Publish Product to Shopify').first().json.images || []).map(i => ({ id: i.id })).concat(($('Wait for Back Images').first().json.body.outputs || []).map(o => ({ src: o.files[0].url }))) }}"
        },
        "authentication": "accessToken"
      },
      "typeVersion": 1
    },
    {
      "id": "01bbf4d7-c566-4136-9e66-17324d343370",
      "name": "Verify Image Existence",
      "type": "n8n-nodes-base.if",
      "position": [
        672,
        656
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "has-image-1",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.images?.[0]?.src ?? '' }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "0df2778f-7f78-4220-9f2b-b579be8785be",
      "name": "Slack Approval Request",
      "type": "n8n-nodes-base.slack",
      "disabled": true,
      "position": [
        2416,
        240
      ],
      "parameters": {
        "select": "channel",
        "message": "=Approve the imagery above for *{{ $('When New Shopify Product Added').first().json.title }}*? *Approve & publish* adds the product shots + on-model shot to the product; *Reject* skips them. (Links stay valid ~12 hours.)",
        "options": {
          "limitWaitTime": {
            "values": {
              "resumeAmount": 12
            }
          }
        },
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "operation": "sendAndWait",
        "authentication": "oAuth2",
        "approvalOptions": {
          "values": {
            "approvalType": "double",
            "approveLabel": "Approve & publish",
            "disapproveLabel": "Reject"
          }
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "d847e880-3d01-44a3-b2d6-ee122bbc84a7",
      "name": "Check Slack Approval",
      "type": "n8n-nodes-base.if",
      "disabled": true,
      "position": [
        2640,
        240
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $json.data.approved }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "845f8da7-c678-4f5d-9c44-4e8d288fa883",
      "name": "Send Images to Slack for Approval",
      "type": "n8n-nodes-base.slack",
      "disabled": true,
      "position": [
        2176,
        64
      ],
      "parameters": {
        "text": "=*New Dreem imagery* for *{{ $('When New Shopify Product Added').first().json.title }}*\nProduct shots:\n{{ ($('Wait for Product Images').first().json.body?.outputs ?? []).map(o => o.files[0].url).join('\\n') }}\nOn-model:\n{{ ($('Wait for Model Images').first().json.body?.outputs ?? []).map(o => o.files[0].url).join('\\n') }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.5
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "c7062405-037b-4e55-8199-3445329b446d",
  "nodeGroups": [],
  "connections": {
    "Check Slack Approval": {
      "main": [
        [
          {
            "node": "Publish Product to Shopify",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for Back Images": {
      "main": [
        [
          {
            "node": "Check Back Image Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for Model Images": {
      "main": [
        [
          {
            "node": "Check Model Image Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create On-Model Images": {
      "main": [
        [
          {
            "node": "Wait for Model Images",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack Approval Request": {
      "main": [
        [
          {
            "node": "Check Slack Approval",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verify Image Existence": {
      "main": [
        [
          {
            "node": "Create Front Product Images",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Back Image Status": {
      "main": [
        [
          {
            "node": "Publish Back Images to Shopify",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Notify on Timeout",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for Product Images": {
      "main": [
        [
          {
            "node": "Check Product Image Status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Model Image Status": {
      "main": [
        [
          {
            "node": "Send Images to Slack for Approval",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Notify on Timeout",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Product Image Status": {
      "main": [
        [
          {
            "node": "Create On-Model Images",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Notify on Timeout",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Back Product Images": {
      "main": [
        [
          {
            "node": "Wait for Back Images",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Publish Product to Shopify": {
      "main": [
        [
          {
            "node": "Create Back Product Images",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Front Product Images": {
      "main": [
        [
          {
            "node": "Wait for Product Images",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When New Shopify Product Added": {
      "main": [
        [
          {
            "node": "Verify Image Existence",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Images to Slack for Approval": {
      "main": [
        [
          {
            "node": "Slack Approval Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}