AutomationFlowsWeb Scraping › Create Dynamic Workflows Programmatically via Webhooks & N8n API

Create Dynamic Workflows Programmatically via Webhooks & N8n API

ByMauricio Perera @rckflr on n8n.io

This workflow exposes an HTTP endpoint (webhook) that accepts a JSON definition of an n8n workflow, validates it, and—if everything is correct—dynamically creates that workflow in the n8n instance via its internal API. If any validation fails or the API call encounters an error,…

Webhook trigger★★★★☆ complexity11 nodesHTTP Request
Web Scraping Trigger: Webhook Nodes: 11 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #4544 — we link there as the canonical source.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "mchujUnGa9RKf7dO",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Create Workflow via Webhook in n8n",
  "tags": [],
  "nodes": [
    {
      "id": "41cfbc58-c8d5-4a22-aec1-72a4b7db3d63",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2360,
        -2100
      ],
      "parameters": {
        "width": 720,
        "height": 500,
        "content": "1. **Webhook**: it receives a POST at `/webhook/create-workflow` with the workflow JSON.\n2. **Validate JSON**: it runs code that checks the JSON has the fields `name` and `nodes`, and that each node has `id`, `name`, `type`, and `position`. It returns `{ success: true }` if everything is valid, or `{ success: false, message: \"\u2026\" }` if there\u2019s an error.\n3. **Validation Successful?**: it looks at the result from \u201cValidate JSON\u201d and, depending on whether `success` is `true` or `false`, decides to continue creating the workflow or return the error.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "62c4a402-1397-4aad-82de-c38672a382a7",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1600,
        -1740
      ],
      "parameters": {
        "color": 3,
        "width": 820,
        "height": 360,
        "content": "1. **Validation Error**: Sets a JSON response with `success: false` and uses the incoming `$json.message` as the error message when the initial payload validation fails.\n\n2. **API Error**: Sets a JSON response with `success: false`, a fixed `message: \"Error creating workflow\"`, includes the full error payload (`error: JSON.stringify($json)`), and the HTTP `statusCode` from the failed API request.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "df771acf-ef37-49f9-8a9f-ec60fd955d86",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1520,
        -2320
      ],
      "parameters": {
        "width": 720,
        "height": 500,
        "content": "1. **Create Workflow**: Sends a POST to `/api/v1/workflows` with the validated workflow payload, using header-based authentication.\n2. **API Successful?**: Checks if the HTTP response status code is \u2264 299.\n3. **Success Response**: If the API call succeeded, constructs the final JSON with `success: true`, `workflowId`, `workflowName`, `createdAt`, and the workflow `url`.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "c798d2a9-577d-4f46-b269-ca2b4447560c",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -2280,
        -1880
      ],
      "parameters": {
        "path": "create-workflow",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "lastNode"
      },
      "notesInFlow": false,
      "typeVersion": 1
    },
    {
      "id": "3ca95b00-83b2-4f75-874f-43a27e298bf1",
      "name": "Validate JSON",
      "type": "n8n-nodes-base.code",
      "position": [
        -2060,
        -1880
      ],
      "parameters": {
        "jsCode": "// Validate the received JSON\nconst payload = $input.item.json.body;\n\n// Check that required fields exist\nif (!payload) {\n  return {\n    json: {\n      success: false,\n      message: \"No payload received in the request\"\n    }\n  };\n}\n\n// Ensure correct format for a workflow\nconst requiredFields = ['name', 'nodes'];\nfor (const field of requiredFields) {\n  if (!payload[field]) {\n    return {\n      json: {\n        success: false,\n        message: `The field '${field}' is required in the workflow`\n      }\n    };\n  }\n}\n\n// Ensure connections and settings exist\nif (!payload.connections) payload.connections = {};\nif (!payload.settings) payload.settings = {};\n\n// Verify that there is at least one node\nif (!Array.isArray(payload.nodes) || payload.nodes.length === 0) {\n  return {\n    json: {\n      success: false,\n      message: \"The workflow must have at least one node\"\n    }\n  };\n}\n\n// Validate each node's required fields\nfor (const node of payload.nodes) {\n  const nodeRequiredFields = ['id', 'name', 'type', 'position'];\n  for (const field of nodeRequiredFields) {\n    if (!node[field]) {\n      return {\n        json: {\n          success: false,\n          message: `Node '${node.name || 'unknown'}' is missing required field '${field}'`\n        }\n      };\n    }\n  }\n  \n  // Ensure parameters exists\n  if (!node.parameters) node.parameters = {};\n  if (!node.typeVersion) node.typeVersion = 1;\n}\n\n// Prepare the workflow object for the API\nconst apiWorkflow = {\n  name: payload.name,\n  nodes: payload.nodes,\n  connections: payload.connections,\n  settings: payload.settings\n};\n\n// If everything is valid, proceed\nreturn {\n  json: {\n    success: true,\n    apiWorkflow: apiWorkflow\n  }\n};"
      },
      "typeVersion": 1
    },
    {
      "id": "b3894755-0583-4c00-b574-e993a6f0b08f",
      "name": "Validation Successful?",
      "type": "n8n-nodes-base.if",
      "position": [
        -1840,
        -1880
      ],
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{ $json.success }}",
              "value2": true
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "ef3a310b-7673-40cc-985a-4e87dc99de70",
      "name": "Create Workflow",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -1440,
        -2080
      ],
      "parameters": {
        "url": "=http://{{ $('Webhook').item.json.headers.host }}/api/v1/workflows",
        "options": {},
        "authentication": "headerAuth"
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1,
      "continueOnFail": true
    },
    {
      "id": "7e2c1a11-1d4c-4075-a03c-f6ed93307d19",
      "name": "API Successful?",
      "type": "n8n-nodes-base.if",
      "position": [
        -1220,
        -2080
      ],
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{ $response.statusCode }}",
              "value2": 299,
              "operation": "smallerEqual"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "0371ce73-ccb6-4e87-8620-4aab8529b170",
      "name": "Success Response",
      "type": "n8n-nodes-base.set",
      "position": [
        -960,
        -2180
      ],
      "parameters": {
        "values": {
          "string": [
            {
              "name": "success",
              "value": "true"
            },
            {
              "name": "message",
              "value": "Workflow created successfully"
            },
            {
              "name": "workflowId",
              "value": "={{ $json.data[0].id }}"
            },
            {
              "name": "workflowName",
              "value": "={{ $json.data[0].name }}"
            },
            {
              "name": "createdAt",
              "value": "={{ $json.data[0].createdAt }}"
            },
            {
              "name": "url",
              "value": "=http://localhost:5678/workflow/{{ $json.data[0].id }}"
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "daec93d7-b9d8-4407-93ab-389b705b0c11",
      "name": "Validation Error",
      "type": "n8n-nodes-base.set",
      "position": [
        -1500,
        -1540
      ],
      "parameters": {
        "values": {
          "string": [
            {
              "name": "success",
              "value": "false"
            },
            {
              "name": "message",
              "value": "={{ $json.message }}"
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "cd2cd403-63c2-42af-a715-9f080067f7d1",
      "name": "API Error",
      "type": "n8n-nodes-base.set",
      "position": [
        -920,
        -1540
      ],
      "parameters": {
        "values": {
          "string": [
            {
              "name": "success",
              "value": "false"
            },
            {
              "name": "message",
              "value": "Error creating workflow"
            },
            {
              "name": "error",
              "value": "={{ JSON.stringify($json) }}"
            },
            {
              "name": "statusCode",
              "value": "={{ $response.statusCode }}"
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 1
    }
  ],
  "active": true,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "849462be-761a-455e-a99b-ffe52b2249d7",
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "Validate JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate JSON": {
      "main": [
        [
          {
            "node": "Validation Successful?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "API Successful?": {
      "main": [
        [
          {
            "node": "Success Response",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "API Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Workflow": {
      "main": [
        [
          {
            "node": "API Successful?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validation Successful?": {
      "main": [
        [
          {
            "node": "Create Workflow",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Validation Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow exposes an HTTP endpoint (webhook) that accepts a JSON definition of an n8n workflow, validates it, and—if everything is correct—dynamically creates that workflow in the n8n instance via its internal API. If any validation fails or the API call encounters an error,…

Source: https://n8n.io/workflows/4544/ — original creator credit. Request a take-down →

More Web Scraping workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Web Scraping

This n8n template provides enterprise-level version control for your workflows using GitHub integration. Stop losing hours to broken workflows and manual exports – get proper commit history, visual di

n8n, Execute Workflow Trigger, HTTP Request +1
Web Scraping

This flow creates dummy files for every item added in your *Arrs (Radarr/Sonarr) with the tag .

HTTP Request, Ssh
Web Scraping

This workflow acts as a central API gateway for all technical indicator agents in the Binance Spot Market Quant AI system. It listens for incoming webhook requests and dynamically routes them to the c

HTTP Request
Web Scraping

Sign PDF documents with legally-compliant digital signatures using X.509 certificates. Supports multiple PAdES signature levels (B, T, LT, LTA) with optional visible stamps.

Execute Command, HTTP Request, Read Write File +1
Web Scraping

📡 This workflow serves as the central Alpha Vantage API fetcher for Tesla trading indicators, delivering cleaned 20-point JSON outputs for three timeframes: , , and . It is required by the following a

HTTP Request