Selbstdokumentierendes API-Portal für Webhooks mit n8n API und Bootstrap generieren
Dies ist ein Document Extraction, Multimodal AI-Bereich Automatisierungsworkflow mit 17 Nodes. Hauptsächlich werden N8n, Set, Code, Html, Webhook und andere Nodes verwendet. Selbstdokumentierende API-Portale für Webhooks mit n8n API und Bootstrap generieren
- •HTTP Webhook-Endpunkt (wird von n8n automatisch generiert)
Verwendete Nodes (17)
Kategorie
{
"meta": {
"instanceId": "e860732ed76ff1de8212e780b2d62bd140dee0b71e6ccf7172d54e965acae43d",
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "a59b516a-e188-4364-8722-f83fd00ed0f0",
"name": "Aggregieren",
"type": "n8n-nodes-base.aggregate",
"position": [
120,
-300
],
"parameters": {
"options": {},
"aggregate": "aggregateAllItemData"
},
"typeVersion": 1
},
{
"id": "3ab41431-6298-4380-aaec-d0e29f7f9cb5",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
-700,
460
],
"webhookId": "e98f9bf5-f5ad-46fb-a93c-08218eea8d5e",
"parameters": {
"path": "api-doc",
"options": {},
"responseMode": "responseNode"
},
"typeVersion": 2
},
{
"id": "286e23f0-44c8-46c4-bfd2-8aab6eae245b",
"name": "Konfigurationen",
"type": "n8n-nodes-base.set",
"position": [
-480,
460
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "9a243289-a359-47fd-9155-a809a910b8f7",
"name": "name_doc",
"type": "string",
"value": "N8N Example Doc"
},
{
"id": "59992f15-d27d-454c-9c1f-a66f0674c7bb",
"name": "version",
"type": "string",
"value": "v.0.1"
},
{
"id": "f0633ecb-b0c8-4e55-8285-51aa05492420",
"name": "description",
"type": "string",
"value": "Example description"
},
{
"id": "2da37a16-f97a-4ec8-9d9c-13f09bea1d39",
"name": "url_base",
"type": "string",
"value": "n8n.io/"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "b910c088-c3c6-4bfc-9856-5294891e4cd0",
"name": "Notizzettel",
"type": "n8n-nodes-base.stickyNote",
"position": [
-370,
-400
],
"parameters": {
"color": 2,
"width": 860,
"height": 260,
"content": "## Get Workflow and filter\n"
},
"typeVersion": 1
},
{
"id": "add44468-ffba-401e-a119-3e25c4870ece",
"name": "Notizzettel1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-360,
-120
],
"parameters": {
"color": 6,
"width": 760,
"height": 400,
"content": "## webhook for testing"
},
"typeVersion": 1
},
{
"id": "1de3f20f-152c-4f81-b42d-cc9e03f5bf0d",
"name": "Antworten",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
120,
-40
],
"parameters": {
"options": {},
"respondWith": "allIncomingItems"
},
"typeVersion": 1.1
},
{
"id": "0a7a9d55-5b34-4129-952d-c982ebcc3d7c",
"name": "HTML-Antwort",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
180,
460
],
"parameters": {
"options": {},
"respondWith": "text",
"responseBody": "={{$json.html}}"
},
"typeVersion": 1.1
},
{
"id": "f85d91a0-16ec-4f79-870a-dfc24f954469",
"name": "Vollständiges HTML erstellen",
"type": "n8n-nodes-base.html",
"position": [
-40,
460
],
"parameters": {
"html": "<html>\n<head>\n <title>{{$('Configs').item.json.name_doc}}</title>\n <link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css\">\n <link href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css\" rel=\"stylesheet\">\n <style>\n :root {\n --bs-body-bg: #1a1a1a;\n --bs-body-color: #e0e0e0;\n --bs-border-color: #444;\n --bs-accordion-bg: #2b2b2b;\n --bs-accordion-color: #e0e0e0;\n --bs-accordion-button-color: #e0e0e0;\n --bs-accordion-border-color: #444;\n --bs-accordion-button-active-bg: #3c3c3c;\n --bs-accordion-button-active-color: #ffffff;\n --bs-accordion-button-focus-border-color: #007bff;\n --bs-accordion-button-focus-box-shadow: 0 0 0 0.25rem rgba(0, 123, 255, 0.25);\n }\n .method {\n display: inline-block;\n padding: 0.3em 0.8em;\n border-radius: 0.25rem;\n font-weight: bold;\n font-size: 0.9em;\n color: white;\n text-transform: uppercase;\n margin-right: 1rem;\n }\n .method-post { background-color: #49cc90; }\n .method-get { background-color: #61affe; }\n .endpoint-path {\n font-family: monospace;\n font-size: 1.1em;\n color: #ccc;\n }\n pre {\n background-color: #161B22;\n padding: 1rem;\n border-radius: 0.25rem;\n white-space: pre-wrap;\n word-break: break-all;\n border: 1px solid var(--bs-border-color);\n }\n code { color: #c9d1d9; }\n .accordion-button:not(.collapsed) {\n box-shadow: inset 0 -1px 0 var(--bs-accordion-border-color);\n }\n </style>\n</head>\n<body class=\"p-4\">\n <div class=\"container\">\n <div class=\"d-flex align-items-baseline mb-4\">\n <h1 class=\"text-white me-3\">{{$('Configs').item.json.name_doc}}</h1>\n <p class=\"text-white-50 me-3\">{{$('Configs').item.json.description}}</p>\n <span class=\"badge bg-secondary\">{{$('Configs').item.json.version}}</span>\n </div>\n \n {{ $json.htmlContent || `\n<div class=\"alert alert-danger d-flex align-items-center mt-4\" role=\"alert\">\n <i class=\"bi bi-x-octagon-fill me-3\" style=\"font-size: 2rem;\"></i>\n <div>\n <h4 class=\"alert-heading\">Documentation Generation Failed!</h4>\n <p>An error occurred while trying to generate the API documentation from the sub-workflow.</p>\n <hr>\n <p class=\"mb-1\"><strong>Please check the following:</strong></p>\n <ul>\n <li>Ensure the sub-workflow (the one that generates the accordion) executed successfully and produced an output named <code>htmlContent</code>.</li>\n <li>Verify that at least one of your workflows is active and contains a correctly configured <code>API_DOCS</code> node.</li>\n <li>Check the n8n execution logs for more detailed error messages from the sub-workflow.</li>\n </ul>\n </div>\n</div>\n`}}\n\n\n </div>\n <footer class=\"mt-5 pt-4 text-center text-white-50\">\n <p>\n Created by <a href=\"https://www.linkedin.com/in/matheus-pedrosa-custodio/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"link-light text-decoration-none\">\n <i class=\"bi bi-linkedin\"></i> Matheus Pedrosa\n </a>\n </p>\n</footer>\n \n <script src=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js\"></script>\n</body>\n</html>"
},
"typeVersion": 1.2
},
{
"id": "0bd66854-cf1b-46b5-ad75-e0d7ef9b71d4",
"name": "Unterarbeitsablauf ausführen",
"type": "n8n-nodes-base.executeWorkflow",
"onError": "continueRegularOutput",
"position": [
-260,
460
],
"parameters": {
"options": {
"waitForSubWorkflow": true
},
"workflowId": {
"__rl": true,
"mode": "list",
"value": "y2xOdk7RyRoS2sgF",
"cachedResultName": "Documentation"
},
"workflowInputs": {
"value": {},
"schema": [
{
"id": "url_base",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "url_base",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": true
}
},
"typeVersion": 1.2
},
{
"id": "43a02f1b-9f18-4148-9705-2c3347997cfa",
"name": "Ausführen",
"type": "n8n-nodes-base.executeWorkflowTrigger",
"position": [
-320,
-300
],
"parameters": {
"workflowInputs": {
"values": [
{
"name": "url_base"
}
]
}
},
"typeVersion": 1.1
},
{
"id": "91ad9f92-adf3-4a8c-af48-3d1e5cd06678",
"name": "Arbeitsabläufe abrufen",
"type": "n8n-nodes-base.n8n",
"position": [
-100,
-300
],
"parameters": {
"filters": {
"tags": "",
"activeWorkflows": true
},
"requestOptions": {}
},
"credentials": {
"n8nApi": {
"id": "fTE1pX6nL40KSIdW",
"name": "n8n account"
}
},
"retryOnFail": true,
"typeVersion": 1,
"alwaysOutputData": false
},
{
"id": "c28819b2-2e5d-4732-9a68-0d5045dcb59e",
"name": "Arbeitsabläufe filtern",
"type": "n8n-nodes-base.code",
"position": [
340,
-300
],
"parameters": {
"jsCode": "const allWorkflows = $('Aggregate').last().json.data;\nlet html = '';\n\nconst documentedWebhookWorkflows = allWorkflows.filter(item => {\n if (!item.nodes || item.nodes.length === 0) {\n return false;\n }\n const hasWebhook = item.nodes.some(node => node.type === 'n8n-nodes-base.webhook');\n const hasDocsNote = item.nodes.some(node => node.type === 'n8n-nodes-base.set' && node.name === 'API_DOCS');\n return hasWebhook && hasDocsNote;\n});\n\n\nif (documentedWebhookWorkflows.length > 0) {\n html += '<div class=\"accordion\" id=\"docsAccordion\">';\n\n const n8nBaseUrl = $(\"Execute\").last().json.url_base || 'https://n8n.io/';\n\n for (const workflow of documentedWebhookWorkflows) {\n const docsNode = workflow.nodes.find(n => n.name === 'API_DOCS');\n\n if (docsNode) {\n const jsonString = docsNode.parameters.jsonOutput || JSON.stringify(docsNode.parameters.docsData);\n let docsData = {};\n let webhookNode = null;\n\n try {\n docsData = JSON.parse(jsonString);\n webhookNode = workflow.nodes.find(n => { return n.type === 'n8n-nodes-base.webhook' && n.name === docsData.webhook });\n } catch (e) {\n console.error(`Erro ao parsear JSON no workflow: ${workflow.name}`, e);\n continue;\n }\n\n if(webhookNode){\n const method = (docsData.method || \"POST\").toUpperCase();\n const uniqueId = webhookNode.parameters.path.replace(/[^a-zA-Z0-9]/g, '');\n\n // --- make CURL\n const fullUrl = `${n8nBaseUrl}webhook/${webhookNode.parameters.path}`;\n\n let curlCommand = `curl -X ${method}\\\\`;\n if (method === 'POST' || method === 'PUT' || method === 'PATCH') {\n const requestBodyString = JSON.stringify(docsData.requestBody || {});\n curlCommand += `\n -H 'Content-Type: application/json' \\\\\n -d '${requestBodyString}' \\\\`;\n }\n curlCommand += `\n ${fullUrl}`;\n\n html += `\n <div class=\"accordion-item\">\n <h2 class=\"accordion-header\" id=\"heading-${uniqueId}\">\n <button class=\"accordion-button collapsed\" type=\"button\" data-bs-toggle=\"collapse\" data-bs-target=\"#collapse-${uniqueId}\" aria-expanded=\"false\" aria-controls=\"collapse-${uniqueId}\">\n <span class=\"method method-${method.toLowerCase()}\">${method}</span>\n <span class=\"endpoint-path\">/webhook/${webhookNode.parameters.path}</span>\n </button>\n </h2>\n <div id=\"collapse-${uniqueId}\" class=\"accordion-collapse collapse\" aria-labelledby=\"heading-${uniqueId}\" data-bs-parent=\"#docsAccordion\">\n <div class=\"accordion-body\">\n <p><strong>${docsData.summary || 'No summary'}</strong></p>\n <p>${docsData.description || 'No description.'}</p>\n <hr style=\"border-color: var(--bs-border-color);\">\n \n <h6>cURL Command:</h6>\n <pre><code>${curlCommand}</code></pre>\n \n <h6>Request Body:</h6>\n <pre><code>${JSON.stringify(docsData.requestBody || {}, null, 2)}</code></pre>\n <h6>Success Response (${docsData.successCode || 'N/A'}):</h6>\n <pre><code>${JSON.stringify(docsData.successResponse || {}, null, 2)}</code></pre>\n <h6>Error Response (${docsData.errorCode || 'N/A'}):</h6>\n <pre><code>${JSON.stringify(docsData.errorResponse || {}, null, 2)}</code></pre>\n </div>\n </div>\n </div>\n `;\n }\n }\n }\n html += '</div>';\n} else {\n html += '<div class=\"alert alert-info\">Nenhum endpoint documentado foi encontrado.</div>';\n}\n\nreturn [{\n json: {\n htmlContent: html\n }\n}];"
},
"typeVersion": 2
},
{
"id": "78526a12-613c-4530-9a6f-bb612036addf",
"name": "Notizzettel2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-940,
-400
],
"parameters": {
"color": 4,
"width": 540,
"height": 700,
"content": "### Live n8n API Documentation Generator\n\n**Author:** Matheus Pedrosa | https://www.linkedin.com/in/matheus-pedrosa-custodio/\n**Version:** 1.0\n**Date:** 2025-08-21\n\n## Summary\nThis is a \"meta-workflow\" that acts as an engine to automatically generate a live, interactive HTML documentation page for your n8n instance's webhooks. It scans all active workflows, finds the ones designated for documentation, and renders a single, professional, dark-themed page.\n\n## Key Feature\nThe core logic relies on a **convention-based discovery**. To include a webhook in the documentation, you simply add a `Set` node named **`API_DOCS`** to that workflow and fill in a JSON object with the endpoint's metadata (summary, request body, responses, etc.). This generator then automatically parses that data to build the documentation page.\n\n## Setup (Quick Checklist)\n1. **`API_DOCS` Nodes:** In every workflow you want to document, add a `Set` node named `API_DOCS` and provide the necessary JSON metadata (especially the `webhookPath`).\n2. **`GetWorkflows` Node:** Configure this node with your `n8n API` credentials. It needs permission to read all workflows.\n3. **`Configs` Node:** Customize the global settings for your documentation page, such as the main title (`name_doc`), description, and version.\n4. **`Webhook` Trigger:** The URL of this workflow's trigger is the public URL for your final documentation page."
},
"typeVersion": 1
},
{
"id": "602d0cd7-558e-4360-b385-bf9824f9278b",
"name": "Webhook1",
"type": "n8n-nodes-base.webhook",
"position": [
-320,
-40
],
"webhookId": "15105da5-96ca-472f-a7db-2ddc2e8b0891",
"parameters": {
"path": "15105da5-96ca-472f-a7db-2ddc2e8b0891",
"options": {},
"responseMode": "responseNode"
},
"typeVersion": 2
},
{
"id": "6283f30d-d1eb-4a7b-9f97-73834d7c060f",
"name": "API_DOKS",
"type": "n8n-nodes-base.set",
"position": [
-320,
120
],
"parameters": {
"mode": "raw",
"options": {},
"jsonOutput": "{\n \"expose\": true,\n \"webhook\": \"Webhook1\",\n \"summary\": \"Title test\",\n \"method\":\"get\",\n \"description\": \"Hey community, look at this cool workflow I'm doing.\",\n \"tags\": [\n \"test\",\n \"tag_0101\"\n ],\n \"requestBody\": {},\n \"successCode\": 200,\n \"successResponse\": {\n \"status\": 200,\n \"message\": \"Workflow start\"\n },\n \"errorCode\": 400,\n \"errorResponse\": {\n \"status\": 500,\n \"message\": \"Workflow error\"\n }\n}"
},
"typeVersion": 3.4
},
{
"id": "57843c34-afb5-401e-86dc-8aa22c242263",
"name": "Simulierte Antwort",
"type": "n8n-nodes-base.code",
"position": [
-100,
-40
],
"parameters": {
"jsCode": "return {\n \"status\": 200,\n \"message\": \"Workflow start\"\n }"
},
"typeVersion": 2
},
{
"id": "29b6b6ea-917b-47a3-b8a1-ff017b0a10a5",
"name": "Notizzettel3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-940,
400
],
"parameters": {
"width": 150,
"height": 200,
"content": "### Create documentation page\n\n"
},
"typeVersion": 1
}
],
"pinData": {},
"connections": {
"286e23f0-44c8-46c4-bfd2-8aab6eae245b": {
"main": [
[
{
"node": "0bd66854-cf1b-46b5-ad75-e0d7ef9b71d4",
"type": "main",
"index": 0
}
]
]
},
"43a02f1b-9f18-4148-9705-2c3347997cfa": {
"main": [
[
{
"node": "91ad9f92-adf3-4a8c-af48-3d1e5cd06678",
"type": "main",
"index": 0
}
]
]
},
"3ab41431-6298-4380-aaec-d0e29f7f9cb5": {
"main": [
[
{
"node": "286e23f0-44c8-46c4-bfd2-8aab6eae245b",
"type": "main",
"index": 0
}
]
]
},
"602d0cd7-558e-4360-b385-bf9824f9278b": {
"main": [
[
{
"node": "57843c34-afb5-401e-86dc-8aa22c242263",
"type": "main",
"index": 0
}
]
]
},
"a59b516a-e188-4364-8722-f83fd00ed0f0": {
"main": [
[
{
"node": "c28819b2-2e5d-4732-9a68-0d5045dcb59e",
"type": "main",
"index": 0
}
]
]
},
"57843c34-afb5-401e-86dc-8aa22c242263": {
"main": [
[
{
"node": "1de3f20f-152c-4f81-b42d-cc9e03f5bf0d",
"type": "main",
"index": 0
}
]
]
},
"91ad9f92-adf3-4a8c-af48-3d1e5cd06678": {
"main": [
[
{
"node": "a59b516a-e188-4364-8722-f83fd00ed0f0",
"type": "main",
"index": 0
}
]
]
},
"f85d91a0-16ec-4f79-870a-dfc24f954469": {
"main": [
[
{
"node": "0a7a9d55-5b34-4129-952d-c982ebcc3d7c",
"type": "main",
"index": 0
}
]
]
},
"c28819b2-2e5d-4732-9a68-0d5045dcb59e": {
"main": [
[]
]
},
"0bd66854-cf1b-46b5-ad75-e0d7ef9b71d4": {
"main": [
[
{
"node": "f85d91a0-16ec-4f79-870a-dfc24f954469",
"type": "main",
"index": 0
}
]
]
}
}
}Wie verwende ich diesen Workflow?
Kopieren Sie den obigen JSON-Code, erstellen Sie einen neuen Workflow in Ihrer n8n-Instanz und wählen Sie "Aus JSON importieren". Fügen Sie die Konfiguration ein und passen Sie die Anmeldedaten nach Bedarf an.
Für welche Szenarien ist dieser Workflow geeignet?
Experte - Dokumentenextraktion, Multimodales KI
Ist es kostenpflichtig?
Dieser Workflow ist völlig kostenlos. Beachten Sie jedoch, dass Drittanbieterdienste (wie OpenAI API), die im Workflow verwendet werden, möglicherweise kostenpflichtig sind.
Verwandte Workflows
Matheus Pedrosa
@julinhoI am a software engineer specializing in automations, with extensive experience on the N8N platform. With solid skills in JavaScript, Go, .NET, and C#, I am equipped to develop efficient and scalable solutions.
Diesen Workflow teilen