{
  "name": "Mockups Generator - render 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 template_id = 'REPLACE_TEMPLATE_ID';\nconst slot_id = 'REPLACE_SLOT_ID';\nconst asset_id = 'REPLACE_ASSET_ID';\nif ([run_key,template_id,slot_id,asset_id].some(v => v.startsWith('REPLACE'))) throw new Error('Configure template_id, exact slot_id, asset_id and stable run_key.');\nreturn [{json:{base_url,run_key,started_at:Date.now(),max_credits:1,acknowledge_preflight_warnings:false,spec:{template_id,options:{format:'png',mode:'full',slots:{[slot_id]:{asset_id,fit:'contain'}}}}}}];"
      }
    },
    {
      "id": "submit-render",
      "name": "Submit render",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        960,
        0
      ],
      "parameters": {
        "method": "POST",
        "url": "={{ $('Workflow settings').first().json.base_url + '/api/v1/render-jobs' }",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {
          "timeout": 60000,
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        },
        "sendBody": true,
        "contentType": "json",
        "specifyBody": "json",
        "jsonBody": "={{ $('Workflow settings').first().json.spec }}",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Idempotency-Key",
              "value": "={{ $('Workflow settings').first().json.run_key }}"
            }
          ]
        }
      },
      "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/render-jobs/' + $('Submit render').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-image",
      "name": "Download image",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2160,
        0
      ],
      "parameters": {
        "method": "GET",
        "url": "={{ $('Workflow settings').first().json.base_url + '/api/v1/render-jobs/' + $('Submit render').first().json.id + '/result' }",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "options": {
          "timeout": 60000,
          "response": {
            "response": {
              "responseFormat": "file",
              "outputPropertyName": "image"
            }
          }
        }
      },
      "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": "Submit render",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Submit render": {
      "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 image",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Wait for worker",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {}
}
