This workflow corresponds to n8n.io template #5174 — 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 →
{
"nodes": [
{
"id": "d776b55a-65fe-4e12-9071-58911fa9c5cc",
"name": "Registered API Keys",
"type": "n8n-nodes-base.set",
"position": [
160,
528
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "2ab01b9f-473f-4f1b-8ddf-8d5a7b706323",
"name": "registered_api_keys",
"type": "array",
"value": "[\n {\n \"user_id\":\"user_1\",\n \"api_key\":\"test\"\n },\n {\n \"user_id\":\"user_2\",\n \"api_key\":\"<redacted-credential>\"\n }\n]"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "d20bdc9b-3020-4fa3-88c3-b6c3d5a585b2",
"name": "API Key Identified",
"type": "n8n-nodes-base.if",
"position": [
480,
0
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "0e476976-504d-4d21-a5d1-849fe54d322f",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
},
"leftValue": "={{ $json.user_id }}",
"rightValue": "={{ $('Secured Webhook').item.json.headers['x-api-key'] }}"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "73ee78a3-9e0c-4f24-a05f-f860dc8fda88",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
128,
-256
],
"parameters": {
"color": 3,
"width": 300,
"height": 420,
"content": "### \u2699\ufe0f Key Verification Logic\n\nThis node takes the API key from the incoming request and asks our \"database\" (the second webhook) if it's valid.\n\n**In a real-world scenario, you would replace this and the nodes below with a single Database node (e.g., Supabase, Postgres) to perform the lookup.**"
},
"typeVersion": 1
},
{
"id": "b34ad49e-351a-4f42-8336-d4300d442c50",
"name": "Respond to Webhook (success)",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
704,
-96
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "={\n \"status\": \"success\",\n \"user_id\": \"{{ $json.user_id }}\"\n}"
},
"typeVersion": 1.4
},
{
"id": "2da5855a-d54a-43f1-b4c5-3ff510a10bd3",
"name": "Respond to Webhook (unauthorized)",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
704,
112
],
"parameters": {
"options": {
"responseCode": 401
},
"respondWith": "json",
"responseBody": "{\n \"error\": \"Please provide a valid x-api-key header.\"\n}"
},
"typeVersion": 1.4
},
{
"id": "0b56b704-4dd6-490a-9998-f8eb2ef0a00e",
"name": "Secured Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
-64,
0
],
"parameters": {
"path": "tutorial/secure-webhook",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode",
"authentication": "headerAuth"
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "7308010d-5050-4e5e-8c8b-c57194b88516",
"name": "Check API Key",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
224,
0
],
"parameters": {
"url": "={{ $env.WEBHOOK_URL + ($env.N8N_ENDPOINT_WEBHOOK ?? \"webhook\") }}/tutorial/secure-webhook/api-keys",
"options": {},
"sendBody": true,
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "api_key",
"value": "={{ $json.headers['x-api-key'] }}"
}
]
},
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2,
"alwaysOutputData": true
},
{
"id": "88070916-27b2-42fb-8005-970b6d5a08fc",
"name": "Find API Key",
"type": "n8n-nodes-base.filter",
"position": [
608,
528
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "526ec1b1-4f6d-41ea-b35a-1347c01aa03a",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.api_key }}",
"rightValue": "={{ $('Get API Key').last().json.body.api_key }}"
}
]
}
},
"typeVersion": 2.2,
"alwaysOutputData": true
},
{
"id": "2a06aaa0-1ac3-4750-9770-6eec7e9310a9",
"name": "Get API Key",
"type": "n8n-nodes-base.webhook",
"position": [
-64,
528
],
"parameters": {
"path": "tutorial/secure-webhook/api-keys",
"options": {},
"responseMode": "lastNode",
"authentication": "headerAuth"
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "3803f9b8-deec-4262-a76b-bfd72d572493",
"name": "Split Out Users",
"type": "n8n-nodes-base.splitOut",
"position": [
384,
528
],
"parameters": {
"options": {},
"fieldToSplitOut": "registered_api_keys"
},
"typeVersion": 1
},
{
"id": "d81a0dd5-9c90-4fee-a7ec-46e9aabb53a3",
"name": "Test Secure Webhook",
"type": "n8n-nodes-base.httpRequest",
"position": [
-416,
0
],
"parameters": {
"url": "={{ $env.WEBHOOK_URL + ($env.N8N_ENDPOINT_WEBHOOK ?? \"webhook\") }}/tutorial/secure-webhook",
"method": "POST",
"options": {},
"sendHeaders": true,
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"headerParameters": {
"parameters": [
{
"name": "x-api-key",
"value": "test"
}
]
}
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "ca63d58d-4683-4dbc-bd1e-6fd2724152f7",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-496,
-176
],
"parameters": {
"color": 6,
"width": 600,
"height": 340,
"content": "### \u25b6\ufe0f Public Endpoint & Tester\n\n* **`Secured Webhook`**: This is your public-facing endpoint. It listens for requests containing an `x-api-key` header.\n* **`Test Secure Webhook`**: Use this node to test the endpoint. Change the `x-api-key` header value to test valid and invalid keys."
},
"typeVersion": 1
},
{
"id": "14afef1c-6a99-46f5-96e1-c536a9afde69",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-144,
320
],
"parameters": {
"color": 7,
"width": 1020,
"height": 380,
"content": "### \ud83d\udce6 Mock Database\n\nThese nodes simulate a database of users and their API keys.\n\n* **`Get API Key`**: A private webhook that receives a key and checks it against the list.\n* **`Registered API Keys`**: **EDIT THIS NODE** to add or remove the API keys you want to be considered valid. Each key should be unique to a user."
},
"typeVersion": 1
},
{
"id": "12074ea9-65a9-4696-8c87-c77842f44467",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
448,
-304
],
"parameters": {
"color": 7,
"width": 440,
"height": 580,
"content": "#### \u2705 Gatekeeper\n\nThis IF node checks the result from our \"database\".\n\n* If a user was found for the given API key, it proceeds to the **success** response.\n* If not, it sends a **401 Unauthorized** error."
},
"typeVersion": 1
},
{
"id": "5a0e2e8a-74df-403d-94ef-d5b8b5a0bd13",
"name": "Sticky Note12",
"type": "n8n-nodes-base.stickyNote",
"position": [
928,
-416
],
"parameters": {
"color": 7,
"width": 540,
"height": 1104,
"content": "## Was this helpful? Let me know!\n[](https://workflows.ac/form)\n\nI really hope this tutorial helped you understand how to build secured webhooks better. Your feedback is incredibly valuable and helps me create better resources for the n8n community.\n\n\n### **Have Feedback, a Question, or a Project Idea?**\n\n\n#### \u27a1\ufe0f **[Click here to go to the Contact Form](https://workflows.ac/form?utm_source=n8n_template&utm_medium=workflow_note&utm_campaign=creating_a_secure_webhook_must_have&utm_content=5174)**\n\nUse this single link for anything you need:\n\n* **Give Feedback:** Share your thoughts on this template, whether you found a typo, encountered an unexpected error, have a suggestion, or just want to say thanks!\n\n* **Automation Coaching:** Get personalized, one-on-one guidance to master n8n. We can work together to help you reach an expert level.\n\n* **Automation Consulting:** Have a complex business challenge or need custom workflows built from scratch? We offer a plug and play automation department for 8 to 88 people teams with unlimited automation requests.\n\n---\n\nHappy Automating!\nLucas Peyrin | [Workflows Accelerator](https://workflows.ac?utm_source=n8n_template&utm_medium=workflow_note&utm_campaign=creating_a_secure_webhook_must_have&utm_content=5174)"
},
"typeVersion": 1
},
{
"id": "bea2b0bd-4175-4e51-9479-7b996ae786e2",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-928,
-176
],
"parameters": {
"width": 400,
"height": 800,
"content": "## \ud83d\udee1\ufe0f Secure Webhook with API Key Verification\n\nStop unauthorized access to your workflows by implementing a robust \"Gatekeeper\" system that verifies API keys against a database before processing any data. This template is perfect for protecting sensitive operations and ensuring only authenticated users can trigger your automations.\n\n* **Public Endpoint:** The workflow starts with a secured webhook that listens for incoming requests and extracts the `x-api-key` from the header.\n* **Validation Logic:** It cross-references the provided key against a \"Mock Database\" (a separate branch in this template acting as a registry). *Note: In production, you would replace this mock section with a real lookup node like Supabase, Postgres, or Airtable.*\n* **Access Control:** Using an IF node, the workflow acts as a gatekeeper: valid keys trigger a success response, while invalid keys are immediately rejected with a 401 Unauthorized error.\n\n---\n\n### Automate your operations today\nYour time is valuable. Let us automate the boring stuff for you.\n\n**\ud83d\udc47 CHOOSE YOUR PATH:**\n\n[ **\u26a1\ufe0f I WANT A FREE AUDIT (2 min)** ](https://workflows.ac/audit?utm_source=n8n_template&utm_medium=workflow_note&utm_campaign=creating_a_secure_webhook_must_have&utm_content=5174)\n> *We've put our heart into this business evaluation machine.*\n\n[ **\ud83d\udca1 I HAVE A SPECIFIC REQUEST** ](https://workflows.ac/form?utm_source=n8n_template&utm_medium=workflow_note&utm_campaign=creating_a_secure_webhook_must_have&utm_content=5174)\n\n"
},
"typeVersion": 1
}
],
"connections": {
"Get API Key": {
"main": [
[
{
"node": "Registered API Keys",
"type": "main",
"index": 0
}
]
]
},
"Check API Key": {
"main": [
[
{
"node": "API Key Identified",
"type": "main",
"index": 0
}
]
]
},
"Secured Webhook": {
"main": [
[
{
"node": "Check API Key",
"type": "main",
"index": 0
}
]
]
},
"Split Out Users": {
"main": [
[
{
"node": "Find API Key",
"type": "main",
"index": 0
}
]
]
},
"API Key Identified": {
"main": [
[
{
"node": "Respond to Webhook (success)",
"type": "main",
"index": 0
}
],
[
{
"node": "Respond to Webhook (unauthorized)",
"type": "main",
"index": 0
}
]
]
},
"Registered API Keys": {
"main": [
[
{
"node": "Split Out Users",
"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.
httpHeaderAuth
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow demonstrates a fundamental pattern for securing a webhook by requiring an API key. It acts as a gatekeeper, checking for a valid key in the request header before allowing the request to proceed. Incoming Request: The node receives an incoming request. It expects an…
Source: https://n8n.io/workflows/5174/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
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
This flow creates dummy files for every item added in your *Arrs (Radarr/Sonarr) with the tag .
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
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.
📡 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