{
  "id": "5BSXfSyLAsQ1XwdA",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "n8n Workflow: Build a MongoDB API with Collection Name Validation and HTTP Responses",
  "tags": [],
  "nodes": [
    {
      "id": "8c193b65-ca41-42ea-92cf-5fa29a0c79ad",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "notes": "Get Collections",
      "position": [
        0,
        80
      ],
      "parameters": {
        "path": ":nameCollection",
        "options": {
          "ignoreBots": false
        },
        "responseMode": "responseNode"
      },
      "notesInFlow": true,
      "typeVersion": 2
    },
    {
      "id": "b623d4a9-7d52-4de2-ae88-9f7f61d60cd9",
      "name": "MongoDB",
      "type": "n8n-nodes-base.mongoDb",
      "position": [
        672,
        -32
      ],
      "parameters": {
        "options": {},
        "collection": "={{ $json.collection }}"
      },
      "credentials": {
        "mongoDb": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "1c4b3f2f-2026-405c-a9c3-c509f0125104",
      "name": "Respond to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1120,
        -32
      ],
      "parameters": {
        "options": {},
        "respondWith": "allIncomingItems"
      },
      "typeVersion": 1.4
    },
    {
      "id": "a60a4fb3-dceb-46da-b513-67fdebcbafd5",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -784,
        -336
      ],
      "parameters": {
        "width": 2224,
        "height": 704,
        "content": "# n8n Workflow: Build a MongoDB API with Collection Name Validation and HTTP Responses\nAuthor: [Samuel Heredia - LinkedIn](https://www.linkedin.com/in/samuel-heredia-2b5b7a98/)\n## **Objective**\nExpose a secure HTTP endpoint that retrieves all documents from a given MongoDB collection. The workflow validates the collection name, queries MongoDB, transforms the response, and returns the result in a clean JSON format.\n\n## **Workflow Steps**"
      },
      "typeVersion": 1
    },
    {
      "id": "bb26c6e7-7d7a-4b24-9f91-0cbe2b54ff9d",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        448,
        80
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "82c6ed89-009d-4e1e-a325-38848aff900b",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.valid }}",
              "rightValue": "false"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "c6e21f82-91d9-4dbe-8ba9-76985bdcc401",
      "name": "Respond code 400",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        672,
        176
      ],
      "parameters": {
        "options": {
          "responseCode": 400
        },
        "respondWith": "json",
        "responseBody": "={\n  \"code\": 400,\n  \"message\": \"{{ $json.message }}\"\n}"
      },
      "typeVersion": 1.4
    },
    {
      "id": "22787b54-c0af-4cc4-bb17-3c452deefaf0",
      "name": "IDS format",
      "type": "n8n-nodes-base.code",
      "position": [
        896,
        -32
      ],
      "parameters": {
        "jsCode": "// Function to replace the '_id' key with 'id' in each object of the array\nfunction replaceIdKey(arr) {\nreturn arr.map(item => {\n// Create a shallow copy of the object to avoid mutating the original\nconst newItem = { ...item };\n// If the object has an '_id' property, replace it with 'id'\nif (newItem._id !== undefined) {\nnewItem.id = newItem._id;\ndelete newItem._id;\n}\nreturn newItem;\n});\n}\n\n// Example usage in n8n Code node:\n// Get the input array from all items\nconst inputArray = $input.all().map(i => i.json);\n// Apply the function to replace '_id' with 'id'\nconst outputArray = replaceIdKey(inputArray);\n\n// If you want to return each object as a separate item:\nreturn outputArray.map(obj => ({ json: obj }));\n\n// If you want to return the whole array as a single item, use this instead:\n// return [{ json: outputArray }];"
      },
      "typeVersion": 2
    },
    {
      "id": "3f406d6d-0fb5-4e04-9620-41cc248a84d7",
      "name": "Validate Pattern",
      "type": "n8n-nodes-base.code",
      "position": [
        224,
        80
      ],
      "parameters": {
        "jsCode": "const name = $input.first().json.params.nameCollection;\nconst regex = /^(?!system\\.)[a-zA-Z0-9._]{1,120}$/;\n\nif (!name) {\n  return { valid: false, message: 'The name Collection cannot be empty.' };\n}\n\nif (!regex.test(name)) {\n  let message = 'The name of the collection does not comply with the rules:';\n  if (name.startsWith('system.')) {\n    message += \"You cannot start with 'system.'. \";\n  }\n  if (name.length < 1 || name.length > 120) {\n    message += 'It must be between 1 and 120 characters long. ';\n  }\n  if (/[^a-zA-Z0-9._]/.test(name)) {\n    message += 'Only letters, numbers, and underscores are allowed. (_) and point (.). ';\n  }\n  return { valid: false, message };\n}\n\nreturn { valid: true, collection: name };"
      },
      "typeVersion": 2
    },
    {
      "id": "db3c923c-adcd-4696-bc53-0e52dae63586",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -816,
        -96
      ],
      "parameters": {
        "color": 5,
        "width": 688,
        "height": 256,
        "content": "## 1. Webhook Node (HTTP GET)\n\n A webhook endpoint is exposed with the following pattern:\n\n```perl\nhttps://<your-n8n-instance>/webhook/<uuid>/:nameCollection\n```\n\nThe :nameCollection parameter in the URL defines which MongoDB collection should be queried.\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "4a24ca29-e8a5-4639-9709-88ceda7171bc",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -816,
        176
      ],
      "parameters": {
        "color": 5,
        "width": 688,
        "height": 336,
        "content": "## 2. Code Node (Validation Layer)\n\nFor security reasons, the provided collection name is validated before any database query is made.\n\nThe regex used is:\n\n```perl\n^(?!system\\.)[a-zA-Z0-9._]{1,120}$\n```\n\nWhy this matters:\nPrevents querying reserved collections (e.g., system.*).\nAvoids injection attempts with malformed names.\nEnsures collection names follow MongoDB\u2019s recommended conventions"
      },
      "typeVersion": 1
    },
    {
      "id": "1ed72099-8556-4ece-bb06-e7d725d08f9a",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -816,
        544
      ],
      "parameters": {
        "color": 5,
        "width": 688,
        "height": 288,
        "content": "## 3. IF Node (Validation Check)\n\n- If the validation passes \u2705: the workflow continues to query MongoDB.\n\n- If validation fails \u274c: the workflow returns a structured HTTP 400 response:\n\n\n```json\n{\n  \"code\": 400,\n  \"message\": \"{{ $json.message }}\"\n}\n```"
      },
      "typeVersion": 1
    },
    {
      "id": "7f2fa3fc-8992-4427-86a1-94846073a9f6",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -816,
        864
      ],
      "parameters": {
        "color": 5,
        "width": 688,
        "height": 176,
        "content": "## 4. MongoDB Node (Data Retrieval)\n\n- Queries the specified collection and retrieves all documents.\n\n- Results are sent downstream for formatting."
      },
      "typeVersion": 1
    },
    {
      "id": "19cf9bdf-9dfc-43e3-b994-4abfb56e3ca3",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -816,
        1088
      ],
      "parameters": {
        "color": 5,
        "width": 688,
        "height": 176,
        "content": "## 5. Code Node (Data Transformation)\n\n- MongoDB documents include an _id field by default.\n\n- This step transforms each record by renaming _id \u2192 id to improve readability and API consistency."
      },
      "typeVersion": 1
    },
    {
      "id": "2041bc0c-5feb-48ab-b85d-2c47e21dec13",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -816,
        1312
      ],
      "parameters": {
        "color": 5,
        "width": 688,
        "height": 176,
        "content": "## 6. Respond to Webhook Node (Final Response)\n\n- Sends back the cleaned MongoDB data as a JSON response to the original HTTP request.\n\n- Ensures clients receive a well-structured, ready-to-use dataset."
      },
      "typeVersion": 1
    },
    {
      "id": "046f1588-6405-42d7-9ca2-e6374beb674f",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -160,
        688
      ],
      "parameters": {
        "color": 3,
        "width": 432,
        "height": 128,
        "content": "## 3.A. Responde code 400\nI respond with standard http :) "
      },
      "typeVersion": 1
    },
    {
      "id": "31ce47f3-062d-4efc-970a-b79c47b080c5",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -48,
        16
      ],
      "parameters": {
        "color": 4,
        "width": 198,
        "height": 240,
        "content": "## 1"
      },
      "typeVersion": 1
    },
    {
      "id": "c0f855d6-82aa-4d4e-b470-b60a5d8a8bce",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        176,
        16
      ],
      "parameters": {
        "color": 4,
        "width": 198,
        "height": 240,
        "content": "## 2"
      },
      "typeVersion": 1
    },
    {
      "id": "c05b5364-b579-4021-8edb-33bb69e7fab0",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        400,
        16
      ],
      "parameters": {
        "color": 4,
        "width": 198,
        "height": 240,
        "content": "## 3"
      },
      "typeVersion": 1
    },
    {
      "id": "c58c0b11-aa59-40ec-9fd5-5bb9fc6ad238",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        608,
        128
      ],
      "parameters": {
        "color": 4,
        "width": 198,
        "height": 176,
        "content": "## 3.A."
      },
      "typeVersion": 1
    },
    {
      "id": "8baaf596-25bb-4fb7-a3e3-a32989d1c930",
      "name": "Sticky Note12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        608,
        -80
      ],
      "parameters": {
        "color": 4,
        "width": 214,
        "height": 192,
        "content": "## 4"
      },
      "typeVersion": 1
    },
    {
      "id": "0abd9d6f-15a2-49fb-9293-d45223c52453",
      "name": "Sticky Note13",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        832,
        -80
      ],
      "parameters": {
        "color": 4,
        "width": 214,
        "height": 192,
        "content": "## 5"
      },
      "typeVersion": 1
    },
    {
      "id": "14f0224b-157e-4776-9cbc-1edd6d73fe09",
      "name": "Sticky Note14",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1072,
        -80
      ],
      "parameters": {
        "color": 4,
        "width": 214,
        "height": 192,
        "content": "## 6"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "a6df2e76-82ca-4802-9955-5d5ca32ff586",
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "MongoDB",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond code 400",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "MongoDB": {
      "main": [
        [
          {
            "node": "IDS format",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook": {
      "main": [
        [
          {
            "node": "Validate Pattern",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IDS format": {
      "main": [
        [
          {
            "node": "Respond to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Pattern": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}