{
  "name": "Mockups Generator - reviewed-collection export",
  "nodes": [
    {
      "id": "run-manually",
      "name": "Run manually",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        0
      ],
      "parameters": {}
    },
    {
      "id": "workflow-settings",
      "name": "Workflow settings",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        240,
        0
      ],
      "parameters": {
        "jsCode": "const base_url = 'https://web.mockupsgenerator.com';\nconst run_key = 'REPLACE_SOURCE_RECORD_AND_ARTWORK_VERSION';\nconst plan_id = 'REPLACE_APPROVED_PLAN_ID';\nconst plan_hash = 'REPLACE_APPROVED_PLAN_HASH';\nif ([run_key,plan_id,plan_hash].some(v => v.startsWith('REPLACE'))) throw new Error('Configure the approved plan and stable run key. Do not regenerate a review on retry.');\nreturn [{json:{base_url,run_key,started_at:Date.now(),spec:{plan_id,plan_hash,idempotency_key:run_key}}}];"
      }
    },
    {
      "id": "preflight",
      "name": "Preflight",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        480,
        0
      ],
      "parameters": {
        "method": "POST",
        "url": "={{ $('Workflow settings').first().json.base_url + '/api/v1/bulk-jobs/preflight' }}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {
          "timeout": 60000,
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        },
        "sendBody": true,
        "contentType": "json",
        "specifyBody": "json",
        "jsonBody": "={{ $('Workflow settings').first().json.spec }}"
      },
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 2000
    },
    {
      "id": "require-valid-plan",
      "name": "Require valid plan",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        720,
        0
      ],
      "parameters": {
        "jsCode": "const cfg = $('Workflow settings').first().json;\nif (!$json.valid) throw new Error(($json.errors || []).map(e => e.message).join('; ') || 'Preflight failed');\nif (!cfg.spec.plan_id && Number($json.total) > cfg.max_credits) throw new Error('Plan exceeds configured max_credits. Review before increasing.');\nif (!cfg.spec.plan_id && ($json.warnings || []).length && !cfg.acknowledge_preflight_warnings) throw new Error('Review preflight warnings and explicitly acknowledge before submitting.');\nreturn $input.all();"
      }
    },
    {
      "id": "submit-collection",
      "name": "Submit collection",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        960,
        0
      ],
      "parameters": {
        "method": "POST",
        "url": "={{ $('Workflow settings').first().json.base_url + '/api/v1/bulk-jobs' }",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {
          "timeout": 60000,
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        },
        "sendBody": true,
        "contentType": "json",
        "specifyBody": "json",
        "jsonBody": "={{ $('Workflow settings').first().json.spec }}"
      },
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 2000
    },
    {
      "id": "wait-for-worker",
      "name": "Wait for worker",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        1200,
        0
      ],
      "parameters": {
        "resume": "timeInterval",
        "amount": 5,
        "unit": "seconds"
      }
    },
    {
      "id": "read-status",
      "name": "Read status",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1440,
        0
      ],
      "parameters": {
        "method": "GET",
        "url": "={{ $('Workflow settings').first().json.base_url + '/api/v1/bulk-jobs/' + $('Submit collection').first().json.id }",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {
          "timeout": 60000,
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        }
      },
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 2000
    },
    {
      "id": "check-job-state",
      "name": "Check job state",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1680,
        0
      ],
      "parameters": {
        "jsCode": "if (['error','cancelled'].includes($json.status)) throw new Error('Job ' + $json.id + ' stopped: ' + ($json.error || $json.status) + '. Preserve ID for recovery.');\nif (!['queued','running','cancelling','done'].includes($json.status)) throw new Error('Unexpected job status');\nif ($json.status !== 'done' && Date.now() - $('Workflow settings').first().json.started_at > 1800000) throw new Error('Polling deadline reached. Preserve job ID; server continues. Resume status reads or resubmit unchanged inputs and SAME key.');\nreturn $input.all();"
      }
    },
    {
      "id": "finished",
      "name": "Finished",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        1920,
        0
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "status-done",
              "leftValue": "={{ $json.status }}",
              "rightValue": "done",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "download-collection",
      "name": "Download collection",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2160,
        0
      ],
      "parameters": {
        "method": "GET",
        "url": "={{ $('Workflow settings').first().json.base_url + '/api/v1/bulk-jobs/' + $('Submit collection').first().json.id + '/result' }",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {
          "timeout": 60000,
          "response": {
            "response": {
              "responseFormat": "file",
              "outputPropertyName": "collection"
            }
          }
        }
      },
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 2000
    },
    {
      "id": "setup-instructions",
      "name": "Setup instructions",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        0,
        -380
      ],
      "parameters": {
        "content": "## Configure before running\nSelect Header Auth on EVERY HTTP node: Authorization = Bearer YOUR_API_KEY. Keep secrets in credentials. Edit Workflow settings with owned IDs and a stable source-record/artwork-version run key. Start manually and persist the accepted job ID. Review warnings before acknowledgement. Rerun unchanged inputs with the SAME key only to recover an operation. Upload the downloaded binary to your destination.\n\nGuide: https://web.mockupsgenerator.com/guides/n8n-mockup-automation",
        "height": 300,
        "width": 580
      }
    }
  ],
  "connections": {
    "Run manually": {
      "main": [
        [
          {
            "node": "Workflow settings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Workflow settings": {
      "main": [
        [
          {
            "node": "Preflight",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Preflight": {
      "main": [
        [
          {
            "node": "Require valid plan",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Require valid plan": {
      "main": [
        [
          {
            "node": "Submit collection",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Submit collection": {
      "main": [
        [
          {
            "node": "Wait for worker",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for worker": {
      "main": [
        [
          {
            "node": "Read status",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read status": {
      "main": [
        [
          {
            "node": "Check job state",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check job state": {
      "main": [
        [
          {
            "node": "Finished",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Finished": {
      "main": [
        [
          {
            "node": "Download collection",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait for worker",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {}
}
