AutomationFlowsData & Sheets › Validate API Requests with Bearer Token Authentication and Airtable

Validate API Requests with Bearer Token Authentication and Airtable

ByNazmy @islamnazmi on n8n.io

This n8n template helps you manage and validate tokens easily using: n8n as your backend workflow engine Airtable as your lightweight token store Stores user tokens securely in Airtable with expiry or usage metadata. Validates incoming tokens in your workflows (e.g., webhook

Webhook trigger★★★★☆ complexity24 nodesAirtableHTTP Request
Data & Sheets Trigger: Webhook Nodes: 24 Complexity: ★★★★☆ Added:

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

This workflow follows the Airtable → HTTP Request recipe pattern — see all workflows that pair these two integrations.

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
{
  "nodes": [
    {
      "id": "a016798d-de6f-418d-9424-3787d9c9f7cc",
      "name": "Active",
      "type": "n8n-nodes-base.if",
      "position": [
        -1880,
        560
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "2e4151fc-f513-4a1d-8e42-c77857de22bc",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json['Is Active'] }}",
              "rightValue": "Active"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "f71b6bbc-8bcf-4d43-9e3e-50b13c1f181e",
      "name": "invalid token",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        -1880,
        760
      ],
      "parameters": {
        "options": {
          "responseCode": 400
        },
        "respondWith": "json",
        "responseBody": "{\n\"success\": false,\n\"error\": \"Invalid token\"\n}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "34a75954-111b-4975-b1c9-ed47ebc48753",
      "name": "expired",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        -1660,
        660
      ],
      "parameters": {
        "options": {
          "responseCode": 401
        },
        "respondWith": "json",
        "responseBody": "{\n\"success\": false,\n\"error\": \"Token is expired\"\n}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "1edc90cc-ca3f-446c-9f8b-1c0818e35f85",
      "name": "Owner?",
      "type": "n8n-nodes-base.if",
      "position": [
        -1220,
        360
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "901aa9e9-2952-44eb-97d1-4f9fcd7e0c74",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Get token').item.json['Issued To'][0] }}",
              "rightValue": "={{ $('Find job').item.json.Users[0] }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "843a59fe-3ace-4b90-9609-bccb165880a2",
      "name": "job not found",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        -1220,
        560
      ],
      "parameters": {
        "options": {
          "responseCode": 404
        },
        "respondWith": "json",
        "responseBody": "{\n\"success\": false,\n\"error\": \"Job not found.\"\n}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "d94d02b7-e7fb-48b9-93fc-ec405c83ef17",
      "name": "unauthorized",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        -1000,
        460
      ],
      "parameters": {
        "options": {
          "responseCode": 401
        },
        "respondWith": "json",
        "responseBody": "{\n\"success\": false,\n\"error\": \"Unauthorized. You don't have the permission to access this job.\"\n}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "df074a23-504f-468c-8ddf-0f09c86fdce1",
      "name": "Other methods",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -2980,
        1100
      ],
      "parameters": {
        "path": "test-jobs",
        "options": {},
        "httpMethod": [
          "POST",
          "DELETE",
          "HEAD",
          "PATCH",
          "PUT"
        ],
        "responseMode": "responseNode",
        "multipleMethods": true
      },
      "typeVersion": 2
    },
    {
      "id": "6f2ffc33-2cfb-4230-bbae-205c3f79fa9b",
      "name": "GET jobs",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -2980,
        760
      ],
      "parameters": {
        "path": "test-jobs",
        "options": {},
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "a123e6ba-8f2a-4217-8917-531081296b74",
      "name": "405 Error",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        -2760,
        1140
      ],
      "parameters": {
        "options": {
          "responseCode": 405
        },
        "respondWith": "json",
        "responseBody": "{\n  \"error\": \"Use GET request instead\"\n}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "715c08ef-401c-46a0-9551-674e06db66ed",
      "name": "Get token",
      "type": "n8n-nodes-base.airtable",
      "position": [
        -2320,
        660
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appbw5TEhn8xIxxXR",
          "cachedResultUrl": "https://airtable.com/appbw5TEhn8xIxxXR",
          "cachedResultName": "Testing Bearer YOUR_TOKEN_HERE "
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblnqvjl4U2t9OMQD",
          "cachedResultUrl": "https://airtable.com/appbw5TEhn8xIxxXR/tblnqvjl4U2t9OMQD",
          "cachedResultName": "Tokens"
        },
        "options": {},
        "operation": "search",
        "filterByFormula": "={token id} = \"{{ $('GET jobs').first().json.headers.authorization.replace('Bearer ', '') }}\""
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1,
      "alwaysOutputData": true
    },
    {
      "id": "b7b3c90a-0bbd-4017-a84e-3e99468918ad",
      "name": "Validator",
      "type": "n8n-nodes-base.code",
      "position": [
        -2760,
        760
      ],
      "parameters": {
        "jsCode": "const input = $json;\n\nconst headers = input.headers || {};\nconst query = input.query || {};\n\nif (!headers.authorization) {\n  return [{ json: { success: false, reason: \"Missing Authorization header\" } }];\n}\n\nif (!headers.authorization.startsWith(\"Bearer \")) {\n  return [{ json: { success: false, reason: \"Authorization header must start with 'Bearer '\" } }];\n}\n\nif (!query.hasOwnProperty(\"job_id\")) {\n  return [{ json: { success: false, reason: \"Missing 'job_id' in query\" } }];\n}\n\nif (Object.keys(query).length !== 1) {\n  return [{ json: { success: false, reason: \"Query must contain only 'job_id'\" } }];\n}\n\nreturn [{ json: { success: true } }];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "d8ebf36f-5715-43e6-8466-f939f15b6a70",
      "name": "Valid",
      "type": "n8n-nodes-base.if",
      "position": [
        -2540,
        760
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "9683899c-af40-414d-bb28-573261ac2c91",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.success }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "3db1de49-9aa2-4d73-96de-2fce13db437c",
      "name": "Unauthorized",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        -2320,
        860
      ],
      "parameters": {
        "options": {
          "responseCode": 401
        },
        "respondWith": "json",
        "responseBody": "={\n  \"error\": \"{{ $json.reason }}\"\n}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "c6104dd7-4bdb-4d49-8ad4-2bc080731566",
      "name": "Find job",
      "type": "n8n-nodes-base.airtable",
      "position": [
        -1660,
        460
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appbw5TEhn8xIxxXR",
          "cachedResultUrl": "https://airtable.com/appbw5TEhn8xIxxXR",
          "cachedResultName": "Testing Bearer YOUR_TOKEN_HERE "
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblS005mLwt03o4vV",
          "cachedResultUrl": "https://airtable.com/appbw5TEhn8xIxxXR/tblS005mLwt03o4vV",
          "cachedResultName": "Jobs"
        },
        "options": {},
        "operation": "search",
        "filterByFormula": "={job id} = \"{{ $('GET jobs').item.json.query.job_id }}\" "
      },
      "credentials": {
        "airtableTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1,
      "alwaysOutputData": true
    },
    {
      "id": "e895c126-e103-43d0-ad72-d2c2c9d25dd9",
      "name": "format job",
      "type": "n8n-nodes-base.code",
      "position": [
        -1000,
        260
      ],
      "parameters": {
        "jsCode": "const record = $json;\n\nconst keyMapping = {\n    \"id\": \"id\",\n    \"createdTime\": \"created_time\",\n    \"Job Title\": \"job_title\",\n    \"Location\": \"location\",\n    \"Job Type\": \"job_type\",\n    \"Company Name\": \"company_name\",\n    \"Number of Applicants\": \"applicants\",\n    \"Salary Midpoint\": \"salary\"\n};\n\nlet jobObject = { success: true };\n\nfor (let key in keyMapping) {\n    if (record[key] !== undefined) {\n        jobObject[keyMapping[key]] = record[key];\n    }\n}\n\nreturn [{\n    json: {\n        job: [jobObject]\n    }\n}];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "f810df27-7b3f-4983-8f40-591be7f1fdd3",
      "name": "Return data",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        -780,
        260
      ],
      "parameters": {
        "options": {
          "responseCode": 200
        },
        "respondWith": "json",
        "responseBody": "={{ $json.job }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "f21827e3-77fb-4889-aacd-dd26edec6978",
      "name": "When clicking \u2018Execute workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -2960,
        380
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "59d6d0fb-89a2-4cf9-8c39-a1e2ed3e28bd",
      "name": "Make a request",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -2740,
        380
      ],
      "parameters": {
        "url": "https://localhost:8080/webhook/test-jobs",
        "options": {},
        "sendQuery": true,
        "sendHeaders": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "job_id",
              "value": "recfCIKgmo9gZUCjj"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_TOKEN_HERE"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "2b5c7b64-b223-4565-8b15-1359368d045b",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3020,
        320
      ],
      "parameters": {
        "color": 7,
        "width": 460,
        "height": 220,
        "content": "## Test the request"
      },
      "typeVersion": 1
    },
    {
      "id": "e106bd6e-2209-40bf-9a52-619b1d71ce3e",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3020,
        1040
      ],
      "parameters": {
        "color": 7,
        "width": 460,
        "height": 280,
        "content": "## HTTP Method handler"
      },
      "typeVersion": 1
    },
    {
      "id": "a3353e22-dca3-43e5-9914-d6cbdfc042b4",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2400,
        560
      ],
      "parameters": {
        "color": 6,
        "width": 260,
        "height": 260,
        "content": "## Database Example\nClone this [Airtable Base](https://airtable.com/appbw5TEhn8xIxxXR/shrN8ve4dfJIXjcAm)"
      },
      "typeVersion": 1
    },
    {
      "id": "a7999c83-fde9-42db-8ed1-8341f970dc9a",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -3640,
        320
      ],
      "parameters": {
        "color": 4,
        "width": 580,
        "height": 1000,
        "content": "## Bearer YOUR_TOKEN_HERE Validation\n\n\nThis n8n template helps you manage and validate tokens easily using:\n\n- n8n as your backend workflow engine  \n- Airtable as your lightweight token store\n\n---\n\n### \ud83d\ude80 What It Does\n\n- Stores user tokens securely in Airtable with expiry or usage metadata.\n- Validates incoming tokens in your workflows (e.g., webhook APIs).\n- Rejects invalid or expired tokens automatically for security.\n- Can be extended to generate, rotate, or revoke tokens for user management.\n\n---\n\n### How It Works\n\n1. **Webhook node** receives requests with a `Bearer` header.\n2. **Airtable Query** looks up the provided token.\n3. **Validation Logic (Code node)**:\n   - Checks if the token exists.\n   - Verifies expiry or usage limits if configured.\n4. Returns **success** if valid, or **error** if error with describing the issue.\n\n---\n\n- Note: This is the simplest way to do auth, just for simplification\n\n---\n\n### Why Use This\n\n- No need for a full backend to manage secure token validation.\n- Clean, modular, and ready for your SaaS workflows.\n\n---\n\nEnjoy building secure automations with **n8n + Airtable**! \ud83d\ude80\n\n### Built by:\n[Nazmy](https://n8n.io/creators/islamnazmi/)"
      },
      "typeVersion": 1
    },
    {
      "id": "36023f3f-f1c2-42b0-a5c7-c378c8ade98b",
      "name": "Token Exists",
      "type": "n8n-nodes-base.if",
      "position": [
        -2100,
        660
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "6f16470a-aae4-4647-850e-332284b00a9f",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.id }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "6d6ec65d-7228-4fd0-a152-071d8d4309f1",
      "name": "Job found?",
      "type": "n8n-nodes-base.if",
      "position": [
        -1440,
        460
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "72d44236-9676-441d-99c7-0c48c5188447",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.id }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    }
  ],
  "connections": {
    "Valid": {
      "main": [
        [
          {
            "node": "Get token",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Unauthorized",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Active": {
      "main": [
        [
          {
            "node": "Find job",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "expired",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Owner?": {
      "main": [
        [
          {
            "node": "format job",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "unauthorized",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find job": {
      "main": [
        [
          {
            "node": "Job found?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GET jobs": {
      "main": [
        [
          {
            "node": "Validator",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get token": {
      "main": [
        [
          {
            "node": "Token Exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validator": {
      "main": [
        [
          {
            "node": "Valid",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Job found?": {
      "main": [
        [
          {
            "node": "Owner?",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "job not found",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "format job": {
      "main": [
        [
          {
            "node": "Return data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Token Exists": {
      "main": [
        [
          {
            "node": "Active",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "invalid token",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Other methods": {
      "main": [
        [
          {
            "node": "405 Error",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "405 Error",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "405 Error",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "405 Error",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "405 Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Make a request",
            "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 n8n template helps you manage and validate tokens easily using: n8n as your backend workflow engine Airtable as your lightweight token store Stores user tokens securely in Airtable with expiry or usage metadata. Validates incoming tokens in your workflows (e.g., webhook…

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

More Data & Sheets workflows → · Browse all categories →

Related workflows

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

Data & Sheets

This premium n8n workflow harnesses the power of DataForSEO's API combined with Airtable's relational database capabilities to transform your keyword research process, providing deeper insights for co

HTTP Request, Airtable
Data & Sheets

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Airtable, HTTP Request, Google Drive +1
Data & Sheets

This workflow automates the entire lifecycle of a service-based client, combining four distinct business flows into a single view: Intake Leads: Receives a webhook from your form builder, validates th

Airtable, Notion, Google Calendar +3
Data & Sheets

It intelligently syncs confirmed sales orders from your Airtable base to QuickBooks, automatically creating new customers if they don't exist before generating a perfectly matched invoice. It then log

Airtable, QuickBooks, HTTP Request
Data & Sheets

Webhook Googlecalendar. Uses stickyNote, httpRequest, respondToWebhook, airtable. Webhook trigger; 33 nodes.

HTTP Request, Airtable, Google Sheets +1