AutomationFlowsGeneral › Build a Full Rest-api with N8n Webhooks

Build a Full Rest-api with N8n Webhooks

ByChristian Knoflach @cknoflac on n8n.io

A clean, extensible REST-style API routing template for n8n webhooks with up to 3 path levels. Serves API routes via Webhooks with path variables Normalizes incoming requests into "global" REQUEST and CFG nodes Flexible routing with Switch-nodes based on path segments & request…

Webhook trigger★★★★★ complexity49 nodes
General Trigger: Webhook Nodes: 49 Complexity: ★★★★★ Added:

This workflow corresponds to n8n.io template #12789 — 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
{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "f791a053-fb25-448a-983a-b34701115af3",
      "name": "-> POST",
      "type": "n8n-nodes-base.set",
      "position": [
        64,
        -288
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "69f54d46-1290-42ea-816a-60b13fbaf6a6",
              "name": "method",
              "type": "string",
              "value": "POST"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "cb9c04d5-08a2-4009-a635-57b7f4a433fa",
      "name": "-> GET",
      "type": "n8n-nodes-base.set",
      "position": [
        64,
        -448
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "69f54d46-1290-42ea-816a-60b13fbaf6a6",
              "name": "method",
              "type": "string",
              "value": "GET"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "ff19ddfc-6e14-421e-84d4-996ed328b67d",
      "name": "-> PUT",
      "type": "n8n-nodes-base.set",
      "position": [
        64,
        -128
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "69f54d46-1290-42ea-816a-60b13fbaf6a6",
              "name": "method",
              "type": "string",
              "value": "PUT"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "09c5b816-e377-44be-8c35-d19b6491a54d",
      "name": "-> DELETE",
      "type": "n8n-nodes-base.set",
      "position": [
        64,
        32
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "69f54d46-1290-42ea-816a-60b13fbaf6a6",
              "name": "method",
              "type": "string",
              "value": "DELETE"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "05be6952-adf6-4644-8874-24b959de3923",
      "name": "v1/seg1",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -224,
        -432
      ],
      "parameters": {
        "path": "/api/v1/:lvl1",
        "options": {},
        "httpMethod": [
          "GET",
          "POST",
          "PUT",
          "DELETE"
        ],
        "responseMode": "responseNode",
        "multipleMethods": true
      },
      "typeVersion": 2.1
    },
    {
      "id": "67fac35a-dd3c-4371-ae47-b519f5734c56",
      "name": "v1/seg2",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -224,
        -240
      ],
      "parameters": {
        "path": "/api/v1/:lvl1/:lvl2",
        "options": {},
        "httpMethod": [
          "GET",
          "POST",
          "PUT",
          "DELETE"
        ],
        "responseMode": "responseNode",
        "multipleMethods": true
      },
      "typeVersion": 2.1
    },
    {
      "id": "b7ea32cb-3d54-4919-8887-4821af6f1180",
      "name": "v1/seg3",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -224,
        -48
      ],
      "parameters": {
        "path": "/api/v1/:lvl1/:lvl2/:lvl3",
        "options": {},
        "httpMethod": [
          "GET",
          "POST",
          "PUT",
          "DELETE"
        ],
        "responseMode": "responseNode",
        "multipleMethods": true
      },
      "typeVersion": 2.1
    },
    {
      "id": "389e112b-176e-43c6-8a98-0346e09bf94f",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -32,
        -720
      ],
      "parameters": {
        "color": 7,
        "width": 1056,
        "height": 928,
        "content": "## Streamlining data \nWe initialize global data for the _REQUEST, and set up our _CFG. We then clear the JSON, so we have a clean separation of global data vs. data flow."
      },
      "typeVersion": 1
    },
    {
      "id": "be718c7a-86a8-4bae-af41-d66e0a15ca5f",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -320,
        -720
      ],
      "parameters": {
        "color": 7,
        "width": 288,
        "height": 928,
        "content": "## API routing levels \n3 levels provide a solid base\n### To add more:\n- Copy the highest-level Webhook-node\n- Add another variable to the end of the path: `/:lvl4`\n- Connect the outputs to the corresponding mode Set-node"
      },
      "typeVersion": 1
    },
    {
      "id": "1d9e81f2-8af2-4df2-9e96-c30357d4518a",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1056,
        -720
      ],
      "parameters": {
        "width": 624,
        "height": 928,
        "content": "# Build REST APIs quickly\n## How it works\nThis template combines webhooks and streamlines data flow for bootstrapping API implementations in n8n.\n\n## Setup\n- This template requires no setup\n- Feel free to set global option in the _CFG node and add/remove levels as needed\n\n## What it can be used for\n- Backend-APIs by using JSON-responses\n- Serving interactive websites by responding with HTML\n- Great for fast, early prototyping\n\n## Notes\n### Direct node notation & \"global\" naming\n- Many nodes don't pass-through data, so relying on $json makes for very cumbersome workflows full of branches -> merges (only to do a DB query, for example)\n- We use global notation instead to keep workflows clean. This template uses the format \"_GLOBAL_NODE_NAME\" for globals, which can be accessed at any point after their execution with $('_GLOBAL_NODE_NAME').item.json\n- See examples in the blue section\n### Noop-nodes\n- No operation nodes help mark entry-points and make it easier to re-route sections\n### n8n restrictions (as of v 2.3.4)\n- webhooks with path variables automatically add a hash as url base\n- webhooks can only map 1:1 to a path level, so each level requires its own webhook"
      },
      "typeVersion": 1
    },
    {
      "id": "3eb25422-1765-4dba-8500-d08197abcb99",
      "name": "_CFG",
      "type": "n8n-nodes-base.code",
      "position": [
        640,
        -208
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "$input.item.json = {\n  debug: true,\n  defaults: {\n    invalid_route: {\n      response: 'requested endpoint not available',\n      status_code: 400\n    }\n  },\n  db: {\n    tables: {\n      internal_label: 'physical_table_name'\n    }\n  },\n  api_base_url: 'auto' // will be automatically extracted below\n};\n\n/*\n  automatic api base url extraction\n*/\nif ($input.item.json.api_base_url === 'auto') {\n  const full = $('_REQUEST').item.json.webhookUrl;\n  const marker = '/api/v';\n  const pos = full.indexOf(marker);\n\n  if (pos === -1)\n    throw new Error(`No api base url for \"${marker}\" in \"${full}\"`);\n\n  const base = full.slice(0, pos);\n  const rest = full.slice(pos + marker.length);\n  const version = rest.match(/^(\\d+)/)?.[1];\n\n  $input.item.json.api_base_url = `${base}${marker}${version}`;\n}\nreturn $input.item;"
      },
      "typeVersion": 2
    },
    {
      "id": "5ce6c0d8-0ce8-43a9-83e0-21ca7d609adc",
      "name": "_REQUEST",
      "type": "n8n-nodes-base.set",
      "position": [
        448,
        -208
      ],
      "parameters": {
        "include": "except",
        "options": {},
        "assignments": {
          "assignments": []
        },
        "excludeFields": "headers",
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "94fd5eb9-1a06-4bbd-988c-80bae085ae7e",
      "name": "Respond to Webhook1",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        3520,
        -592
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={{ $('_REQUEST').item.json }}"
      },
      "typeVersion": 1.5
    },
    {
      "id": "aeb33496-b122-4a90-ae66-66ded2c135ae",
      "name": "Invalid Route",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1488,
        -80
      ],
      "parameters": {
        "options": {
          "responseCode": "={{ $('_CFG').item.json.defaults.invalid_route.status_code }}"
        },
        "respondWith": "text",
        "responseBody": "={{ $('_CFG').item.json.defaults.invalid_route.response }}"
      },
      "typeVersion": 1.5
    },
    {
      "id": "6269dca9-e433-40a2-ae07-13e32f6e0dbf",
      "name": "Clear JSON",
      "type": "n8n-nodes-base.set",
      "position": [
        832,
        -208
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3.4,
      "alwaysOutputData": true
    },
    {
      "id": "627ab5bb-bf94-4609-8fae-bb6a97904420",
      "name": "Invalid Route1",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1872,
        -80
      ],
      "parameters": {
        "options": {
          "responseCode": "={{ $('_CFG').item.json.defaults.invalid_route.status_code }}"
        },
        "respondWith": "text",
        "responseBody": "={{ $('_CFG').item.json.defaults.invalid_route.response }}"
      },
      "typeVersion": 1.5
    },
    {
      "id": "0a4fc685-916b-4703-b6fd-be67d3663ba5",
      "name": "Invalid Route2",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        2256,
        -336
      ],
      "parameters": {
        "options": {
          "responseCode": "={{ $('_CFG').item.json.defaults.invalid_route.status_code }}"
        },
        "respondWith": "text",
        "responseBody": "={{ $('_CFG').item.json.defaults.invalid_route.response }}"
      },
      "typeVersion": 1.5
    },
    {
      "id": "c99025cd-cbcb-427c-a87c-5bc110ebd4a4",
      "name": "Invalid Route3",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        2256,
        64
      ],
      "parameters": {
        "options": {
          "responseCode": "={{ $('_CFG').item.json.defaults.invalid_route.status_code }}"
        },
        "respondWith": "text",
        "responseBody": "={{ $('_CFG').item.json.defaults.invalid_route.response }}"
      },
      "typeVersion": 1.5
    },
    {
      "id": "62b6dbef-116b-4949-8e6f-e70e676c0bcf",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        3520,
        -384
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={{ $('_REQUEST').item.json }}"
      },
      "typeVersion": 1.5
    },
    {
      "id": "f6d82071-1a0a-457d-b09e-9a61120c07b4",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1200,
        -720
      ],
      "parameters": {
        "color": 7,
        "width": 1296,
        "height": 928,
        "content": "## Endpoint-based routing\nDuplicated fallback nodes to prevent visual clutter, all fallbacks can ofc also route to a centralized flow."
      },
      "typeVersion": 1
    },
    {
      "id": "ec02dbe3-82e1-4398-98e1-111ce7d01b6b",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2656,
        -720
      ],
      "parameters": {
        "color": 4,
        "width": 1168,
        "height": 544,
        "content": "## Endpoint Implementation\nSubworkflows are used as a placeholder, implementation can ofc also just be inline.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "80e850ec-66c5-4537-8c26-5bd128bc8676",
      "name": "Routing",
      "type": "n8n-nodes-base.noOp",
      "position": [
        1296,
        -208
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "2fc22f0a-df85-49d9-8e21-80de2c3c9a75",
      "name": "Check baz status",
      "type": "n8n-nodes-base.noOp",
      "position": [
        3136,
        -592
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "90650048-1797-420e-b8bd-1032aec09742",
      "name": "Create new baz",
      "type": "n8n-nodes-base.noOp",
      "position": [
        3136,
        -384
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "0279ee50-54df-4d2d-b1ed-7fdf6ebb652b",
      "name": "Implementation",
      "type": "n8n-nodes-base.executeWorkflow",
      "onError": "continueRegularOutput",
      "position": [
        3328,
        -592
      ],
      "parameters": {
        "source": "parameter",
        "options": {
          "waitForSubWorkflow": false
        },
        "workflowJson": "{}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "0050daa5-2edb-484b-abb7-c618cd442abc",
      "name": "Implementation1",
      "type": "n8n-nodes-base.executeWorkflow",
      "onError": "continueRegularOutput",
      "position": [
        3328,
        -384
      ],
      "parameters": {
        "source": "parameter",
        "options": {
          "waitForSubWorkflow": false
        },
        "workflowJson": "{}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "34b83843-804b-43f6-8475-623ecc63b89a",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -304,
        320
      ],
      "parameters": {
        "color": 5,
        "width": 1248,
        "height": 1200,
        "content": "## Example for $json-based vs. absolute $('_NODE') notation for data access\nNodes that don't pass through content, like DB nodes, require cumbersome and cluttersome branching -> merging to preserve the n8n default principle of continuous data flow via the $json object. \n\nAs an alternative, absolute node references can help tremendously to reduce visual clutter. Support for absolute references is very good:\n- when renaming a target node, any absolute call reference will automatically update to the new name\n- when copying a whole section of a workflow that includes absolute references AND the target node, absolute references will be updated to the new target copy\n\nIn order to be able to reference a node:\n- the target node must be on the path to the node you are trying to reference it from\n- the target node must have been executed (check method in example)\n"
      },
      "typeVersion": 1
    },
    {
      "id": "b1fe6080-4edc-4d15-91f0-f56bb352abf2",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        560,
        672
      ],
      "parameters": {
        "mode": "chooseBranch"
      },
      "typeVersion": 3.2
    },
    {
      "id": "acbfccc8-be97-4000-96af-b57b634a9b8a",
      "name": "/foo",
      "type": "n8n-nodes-base.switch",
      "position": [
        1872,
        -240
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "025bf7d8-484b-4457-898a-55a8a39b3933",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ $('_REQUEST').item.json.params.lvl2 == 'bar' }}",
                    "rightValue": "bar"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "bcbcd98d-625a-47ce-b752-90500c92fdf1",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ $('_REQUEST').item.json.params.lvl2 == 'qux'}}",
                    "rightValue": "qux"
                  }
                ]
              }
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra"
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "8c8a1559-4246-4711-80dd-2806f9f853e0",
      "name": "api root",
      "type": "n8n-nodes-base.switch",
      "position": [
        1488,
        -208
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "025bf7d8-484b-4457-898a-55a8a39b3933",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ $('_REQUEST').item.json.params.lvl1 == 'foo' }}",
                    "rightValue": "foo"
                  }
                ]
              }
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra"
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "be329dc0-6874-44d5-8989-f8728197623e",
      "name": "/foo/bar/baz",
      "type": "n8n-nodes-base.noOp",
      "position": [
        2752,
        -480
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "bef1ea6a-2e91-4f39-99f1-81676b53dbe5",
      "name": "/foo/bar",
      "type": "n8n-nodes-base.switch",
      "position": [
        2256,
        -464
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "a9e83028-162c-4b75-8d3b-b747bff055a8",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ $('_REQUEST').item.json.params.lvl3 == 'baz'}}",
                    "rightValue": "baz"
                  }
                ]
              }
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra"
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "7732d88e-bc8c-4d74-9c99-c26d90437c67",
      "name": "/foo/qux",
      "type": "n8n-nodes-base.switch",
      "position": [
        2256,
        -64
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "",
                    "rightValue": ""
                  }
                ]
              }
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra"
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "ca1c3fd7-05bf-426b-8fb8-68044cc5cb9b",
      "name": "baz METHOD",
      "type": "n8n-nodes-base.switch",
      "position": [
        2944,
        -480
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "GET",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "a9e83028-162c-4b75-8d3b-b747bff055a8",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $('_REQUEST').item.json.method }}",
                    "rightValue": "GET"
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "POST",
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "355515a7-d7ce-4c4b-a665-4dcaac5d401a",
                    "operator": {
                      "name": "filter.operator.equals",
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $('_REQUEST').item.json.method }}",
                    "rightValue": "POST"
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {
          "fallbackOutput": "none"
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "fdf361ac-b211-4051-a666-6e72f7a9070e",
      "name": "regular Set node",
      "type": "n8n-nodes-base.set",
      "position": [
        176,
        656
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "4b98db71-2a59-411f-b28f-e484d414f096",
              "name": "test",
              "type": "string",
              "value": "we need this value"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "f910dc32-f762-464b-a938-3536a97b3f8b",
      "name": "non-passthrough node",
      "type": "n8n-nodes-base.executeWorkflow",
      "onError": "continueRegularOutput",
      "position": [
        368,
        768
      ],
      "parameters": {
        "source": "parameter",
        "options": {
          "waitForSubWorkflow": false
        },
        "workflowJson": "{}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "4985acc4-ba09-4fd1-bb97-acd75b2ac7da",
      "name": "data via $json",
      "type": "n8n-nodes-base.set",
      "position": [
        752,
        672
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a0218318-24e6-4312-a7e3-397f626bf695",
              "name": "test",
              "type": "string",
              "value": "={{ $json.test }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "57eb16cd-ffb2-4894-92a0-805396778504",
      "name": "Named node",
      "type": "n8n-nodes-base.set",
      "position": [
        176,
        992
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "c984797c-e667-4f38-811b-446fca3dac9b",
              "name": "test",
              "type": "string",
              "value": "we need this value"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "04cf9504-4620-4f85-820c-b6fcbcb6d6f7",
      "name": "non-passthrough node1",
      "type": "n8n-nodes-base.executeWorkflow",
      "onError": "continueRegularOutput",
      "position": [
        368,
        992
      ],
      "parameters": {
        "source": "parameter",
        "options": {
          "waitForSubWorkflow": false
        },
        "workflowJson": "{}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "f11e1ff4-c857-48f2-bd1b-c883a54e6ff2",
      "name": "data via $('NODE')",
      "type": "n8n-nodes-base.set",
      "position": [
        752,
        992
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a0218318-24e6-4312-a7e3-397f626bf695",
              "name": "test",
              "type": "string",
              "value": "={{ $('Named node').item.json.test }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "fa0a2770-f870-47af-9028-faa3a33b5ae6",
      "name": "example: default $json-based",
      "type": "n8n-nodes-base.noOp",
      "position": [
        -16,
        656
      ],
      "parameters": {},
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "9ebccd9d-2f38-4b02-a3ae-253a6ab86c99",
      "name": "example: $('NODE') based",
      "type": "n8n-nodes-base.noOp",
      "position": [
        -16,
        992
      ],
      "parameters": {},
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "6455c350-2f78-446e-a0c7-fbf74edce36f",
      "name": "example: check for execution",
      "type": "n8n-nodes-base.noOp",
      "position": [
        -16,
        1296
      ],
      "parameters": {},
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "c905835f-82fa-41f6-a270-742e6e855b2b",
      "name": "run examples",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -208,
        992
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "7bde2def-0994-4d53-b1b3-45ee11ade62c",
      "name": "optional path",
      "type": "n8n-nodes-base.set",
      "position": [
        368,
        1200
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a622a46b-b7d2-47a2-a8fd-f4aaae4dd6de",
              "name": "test",
              "type": "string",
              "value": "we need this value"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "3c111485-8699-47c6-8c16-90f570b498bd",
      "name": "50:50 randomizer",
      "type": "n8n-nodes-base.if",
      "position": [
        176,
        1296
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "38fa5843-9499-479e-b6ed-7465c05f76ee",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ Math.random() >= 0.5 }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "a61bdd62-e908-4063-896d-41b677c7628f",
      "name": "non-passthrough node2",
      "type": "n8n-nodes-base.executeWorkflow",
      "onError": "continueRegularOutput",
      "position": [
        560,
        1312
      ],
      "parameters": {
        "source": "parameter",
        "options": {
          "waitForSubWorkflow": false
        },
        "workflowJson": "{}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "0731df76-749d-4a65-9b55-c2041a39a074",
      "name": "data with fallback",
      "type": "n8n-nodes-base.set",
      "position": [
        752,
        1312
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a0218318-24e6-4312-a7e3-397f626bf695",
              "name": "test",
              "type": "string",
              "value": "={{ $('optional path').isExecuted ? $('optional path').item.json.test : 'node not executed' }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "829745fe-f822-429a-8fad-5b701ab91417",
      "name": "API entry point",
      "type": "n8n-nodes-base.noOp",
      "position": [
        256,
        -208
      ],
      "parameters": {},
      "typeVersion": 1
    }
  ],
  "connections": {
    "/foo": {
      "main": [
        [
          {
            "node": "/foo/bar",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "/foo/qux",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Invalid Route1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "_CFG": {
      "main": [
        [
          {
            "node": "Clear JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "data via $json",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "-> GET": {
      "main": [
        [
          {
            "node": "API entry point",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "-> PUT": {
      "main": [
        [
          {
            "node": "API entry point",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "-> POST": {
      "main": [
        [
          {
            "node": "API entry point",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Routing": {
      "main": [
        [
          {
            "node": "api root",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "v1/seg1": {
      "main": [
        [
          {
            "node": "-> GET",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "-> POST",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "-> PUT",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "-> DELETE",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "v1/seg2": {
      "main": [
        [
          {
            "node": "-> GET",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "-> POST",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "-> PUT",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "-> DELETE",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "v1/seg3": {
      "main": [
        [
          {
            "node": "-> GET",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "-> POST",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "-> PUT",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "-> DELETE",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "/foo/bar": {
      "main": [
        [
          {
            "node": "/foo/bar/baz",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Invalid Route2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "/foo/qux": {
      "main": [
        [
          {
            "node": "Invalid Route3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "_REQUEST": {
      "main": [
        [
          {
            "node": "_CFG",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "api root": {
      "main": [
        [
          {
            "node": "/foo",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Invalid Route",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "-> DELETE": {
      "main": [
        [
          {
            "node": "API entry point",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clear JSON": {
      "main": [
        [
          {
            "node": "Routing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Named node": {
      "main": [
        [
          {
            "node": "non-passthrough node1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "baz METHOD": {
      "main": [
        [
          {
            "node": "Check baz status",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create new baz",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "/foo/bar/baz": {
      "main": [
        [
          {
            "node": "baz METHOD",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "run examples": {
      "main": [
        [
          {
            "node": "example: default $json-based",
            "type": "main",
            "index": 0
          },
          {
            "node": "example: $('NODE') based",
            "type": "main",
            "index": 0
          },
          {
            "node": "example: check for execution",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "optional path": {
      "main": [
        [
          {
            "node": "non-passthrough node2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create new baz": {
      "main": [
        [
          {
            "node": "Implementation1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Implementation": {
      "main": [
        [
          {
            "node": "Respond to Webhook1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "API entry point": {
      "main": [
        [
          {
            "node": "_REQUEST",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Implementation1": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "50:50 randomizer": {
      "main": [
        [
          {
            "node": "optional path",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "non-passthrough node2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check baz status": {
      "main": [
        [
          {
            "node": "Implementation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "regular Set node": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          },
          {
            "node": "non-passthrough node",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "non-passthrough node": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "non-passthrough node1": {
      "main": [
        [
          {
            "node": "data via $('NODE')",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "non-passthrough node2": {
      "main": [
        [
          {
            "node": "data with fallback",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "example: $('NODE') based": {
      "main": [
        [
          {
            "node": "Named node",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "example: check for execution": {
      "main": [
        [
          {
            "node": "50:50 randomizer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "example: default $json-based": {
      "main": [
        [
          {
            "node": "regular Set node",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

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

About this workflow

A clean, extensible REST-style API routing template for n8n webhooks with up to 3 path levels. Serves API routes via Webhooks with path variables Normalizes incoming requests into "global" REQUEST and CFG nodes Flexible routing with Switch-nodes based on path segments & request…

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

More General workflows → · Browse all categories →

Related workflows

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

General

PUQ Docker NextCloud deploy. Uses respondToWebhook, stickyNote, httpRequest, ssh. Webhook trigger; 44 nodes.

HTTP Request, Ssh
General

puq-docker-immich-deploy. Uses respondToWebhook, ssh, stickyNote. Webhook trigger; 35 nodes.

Ssh
General

Analyze_email_headers_for_IPs_and_spoofing__3. Uses stickyNote, respondToWebhook, itemLists, httpRequest. Webhook trigger; 35 nodes.

Item Lists, HTTP Request
General

puq-docker-n8n-deploy. Uses respondToWebhook, ssh, stickyNote. Webhook trigger; 34 nodes.

Ssh
General

puq-docker-influxdb-deploy. Uses respondToWebhook, ssh, stickyNote. Webhook trigger; 33 nodes.

Ssh