AutomationFlowsEmail & Gmail › Automate Document Approvals with Multi-level Workflows Using Supabase & Gmail

Automate Document Approvals with Multi-level Workflows Using Supabase & Gmail

ByAlok Kumar @alokkumar on n8n.io

This workflow automates a document approval process using Supabase and Gmail. Teams that need structured multi-level document approvals. Companies managing policies, contracts, or proposals. Medical document need multiple lavel of review and approval. Form Trigger – A user…

Webhook trigger★★★★★ complexity38 nodesSupabaseCryptoGmailForm TriggerHTTP RequestForm
Email & Gmail Trigger: Webhook Nodes: 38 Complexity: ★★★★★ Added:
Automate Document Approvals with Multi-level Workflows Using Supabase & Gmail — n8n workflow card showing Supabase, Crypto, Gmail integration

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

This workflow follows the Form → Form Trigger 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
{
  "id": "5myl9GWWVupDIebk",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Multi-Level Document Approval & Audit Workflow",
  "tags": [],
  "nodes": [
    {
      "id": "9e61af97-d649-4260-becd-ea8865bad9ff",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -560,
        1104
      ],
      "parameters": {
        "path": "approve",
        "options": {},
        "responseMode": "responseNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "cb8cc119-29a2-48e7-84bf-81f79d57c27e",
      "name": "Audit1",
      "type": "n8n-nodes-base.supabase",
      "position": [
        -256,
        2032
      ],
      "parameters": {
        "tableId": "audit_logs",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "document_id",
              "fieldValue": "={{ $('get_approval_data').item.json.document_id }}"
            },
            {
              "fieldId": "action",
              "fieldValue": "approval_sent"
            },
            {
              "fieldId": "actor_email",
              "fieldValue": "system@workflow"
            },
            {
              "fieldId": "details",
              "fieldValue": "=Level {{ $('get_next_level').item.json.level_number }}  requests sent to role_id {{ $('generate_uuid').item.json.role_id}} "
            }
          ]
        }
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "7dd27017-db27-40d2-ae81-1f5e8bd296b5",
      "name": "Final Update Document",
      "type": "n8n-nodes-base.supabase",
      "position": [
        80,
        1808
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "id",
              "keyValue": "={{ $('get_approval_data').item.json.document_id }}",
              "condition": "eq"
            }
          ]
        },
        "tableId": "documents",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "status",
              "fieldValue": "={{ $json.status }}"
            },
            {
              "fieldId": "updated_at",
              "fieldValue": "={{ new Date(Date.now()).toISOString() }}"
            }
          ]
        },
        "operation": "update"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "564ca96f-4b65-4f0b-b075-1a02eed98893",
      "name": "save_document",
      "type": "n8n-nodes-base.supabase",
      "position": [
        816,
        0
      ],
      "parameters": {
        "tableId": "documents",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "title",
              "fieldValue": "={{ $('start_approval_form').item.json.Title }}"
            },
            {
              "fieldId": "content",
              "fieldValue": "={{ $('start_approval_form').item.json.data[0].filename }}"
            },
            {
              "fieldId": "submitted_by",
              "fieldValue": "1"
            },
            {
              "fieldId": "status",
              "fieldValue": "Pending"
            }
          ]
        }
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "98fbb076-c588-4e88-8a62-b91c6adab3c2",
      "name": "get_workflow_level_one",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1184,
        0
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "level_number",
              "keyValue": "1"
            }
          ]
        },
        "tableId": "workflow_levels",
        "operation": "get"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "550fde74-26c2-4a04-bfcb-cc801f2bdf50",
      "name": "get_user_by_role",
      "type": "n8n-nodes-base.supabase",
      "position": [
        448,
        224
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "role_id",
              "keyValue": "={{ $json.role_id }}",
              "condition": "eq"
            }
          ]
        },
        "tableId": "users",
        "operation": "getAll",
        "returnAll": true
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "d45ef572-ca77-4e3b-b040-933d14d54763",
      "name": "create_uuid_token",
      "type": "n8n-nodes-base.crypto",
      "position": [
        816,
        224
      ],
      "parameters": {
        "action": "generate"
      },
      "typeVersion": 1
    },
    {
      "id": "5b325046-052d-4f11-960c-f97a6ac79703",
      "name": "create_record_approvals",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1184,
        224
      ],
      "parameters": {
        "tableId": "approvals",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "document_id",
              "fieldValue": "={{ $('save_document').item.json.id }}"
            },
            {
              "fieldId": "level_id",
              "fieldValue": "={{ $('get_workflow_level_one').item.json.id }}"
            },
            {
              "fieldId": "approver_id",
              "fieldValue": "={{ $json.id }}"
            },
            {
              "fieldId": "token",
              "fieldValue": "={{ $json.data }}"
            },
            {
              "fieldId": "status",
              "fieldValue": "={{ $('save_document').item.json.status }}"
            },
            {
              "fieldId": "expiry_time",
              "fieldValue": "={{ new Date(Date.now() + 48 * 60 * 60 * 1000) }}"
            }
          ]
        }
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "cd4dc454-6893-44d7-89d5-b4703e1787d7",
      "name": "send_email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        816,
        464
      ],
      "parameters": {
        "sendTo": "={{ $('create_uuid_token').item.json.email }}",
        "message": "=<p>Please review: {{ $('save_document').item.json.title }}</p>\n<p>\n  <a href=\"http://localhost:5678/webhook-test/doc-approval/approve?token={{$json.token}}&decision=approved\">Approve</a> |\n  <a href=\"http://localhost:5678/webhook-test/doc-approvalapprove?token={{$json.token}}&decision=rejected\">Reject</a>\n</p>",
        "options": {
          "attachmentsUi": {
            "attachmentsBinary": [
              {}
            ]
          }
        },
        "subject": "=Document Approval Request -  {{ $('save_document').item.json.title }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "879f0811-789f-426e-8a09-caf7c326b3fc",
      "name": "audit_invites",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1200,
        464
      ],
      "parameters": {
        "tableId": "audit_logs",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "document_id",
              "fieldValue": "={{ $('save_document').item.json.id }}"
            },
            {
              "fieldId": "action",
              "fieldValue": "approval_sent"
            },
            {
              "fieldId": "actor_email",
              "fieldValue": "system@workflow"
            },
            {
              "fieldId": "details",
              "fieldValue": "=Level 1 requests sent to role_id {{ $('get_workflow_level_one').item.json.role_id}} "
            }
          ]
        }
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "4c3db623-dc84-47cd-81c3-2d1553f0218b",
      "name": "start_approval_form",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        128,
        0
      ],
      "parameters": {
        "options": {
          "path": "approval-process-start",
          "ignoreBots": true,
          "buttonLabel": "Send for Approval",
          "appendAttribution": true,
          "useWorkflowTimezone": true
        },
        "formTitle": "Document Approval",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Title",
              "placeholder": "Give some Title of document ",
              "requiredField": true
            },
            {
              "fieldType": "textarea",
              "fieldLabel": "Description",
              "placeholder": "Describe what document all about. "
            },
            {
              "fieldType": "file",
              "fieldLabel": "data",
              "requiredField": true,
              "acceptFileTypes": ".pdf"
            }
          ]
        },
        "formDescription": "Document Approval Workflow "
      },
      "typeVersion": 2.2,
      "alwaysOutputData": false
    },
    {
      "id": "3523cf77-050b-46f7-b06e-975ae91c606f",
      "name": "get_approval_data",
      "type": "n8n-nodes-base.supabase",
      "position": [
        -272,
        1104
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "token",
              "keyValue": "={{ $json.query.token }}"
            }
          ]
        },
        "tableId": "approvals",
        "operation": "get"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "0047e141-6fe8-40b3-b998-874e2c3fa018",
      "name": "update_approval_data",
      "type": "n8n-nodes-base.supabase",
      "position": [
        416,
        1088
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "approver_id",
              "keyValue": "={{ $json.approver_id }}",
              "condition": "eq"
            },
            {
              "keyName": "status",
              "keyValue": "Pending",
              "condition": "eq"
            },
            {
              "keyName": "token",
              "keyValue": "={{ $json.token }}",
              "condition": "eq"
            }
          ]
        },
        "tableId": "approvals",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "status",
              "fieldValue": "={{ $('Webhook').item.json.query.decision }}"
            },
            {
              "fieldId": "acted_at",
              "fieldValue": "={{ new Date(Date.now()).toISOString() }}"
            }
          ]
        },
        "matchType": "allFilters",
        "operation": "update"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "4f6b45fc-e8de-469d-a936-de70f9c890c0",
      "name": "check_reject_or_approve",
      "type": "n8n-nodes-base.if",
      "position": [
        800,
        1088
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "6222263f-cd22-457d-8446-b19f7e1b6ffb",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Webhook').item.json.query.decision }}",
              "rightValue": "approved"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "6afc3654-1ac1-43a0-a800-2d60a676f336",
      "name": "get_level_details",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1168,
        1072
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "id",
              "keyValue": "={{ $('get_approval_data').item.json.level_id }}"
            }
          ]
        },
        "tableId": "workflow_levels",
        "operation": "get"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "e8913824-5efa-46f2-b95d-d065491b63b1",
      "name": "get_next_level",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1520,
        1072
      ],
      "parameters": {
        "limit": 1,
        "filters": {
          "conditions": [
            {
              "keyName": "level_number",
              "keyValue": "={{ $json.level_number }}",
              "condition": "gt"
            }
          ]
        },
        "tableId": "workflow_levels",
        "operation": "getAll"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "ced013ad-e2c4-42b0-9a4a-63198d442a21",
      "name": "is_last_level",
      "type": "n8n-nodes-base.if",
      "position": [
        -544,
        1456
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "fb67a0fe-ced5-47a8-8f08-805d4253d0cf",
              "operator": {
                "type": "object",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $('get_next_level').item.json }}",
              "rightValue": "={{ {} }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "8ab1e933-546e-4f31-8e4b-f40e6fd24ccc",
      "name": "get_workflow_by_level",
      "type": "n8n-nodes-base.supabase",
      "position": [
        -272,
        1440
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "level_number",
              "keyValue": "= {{ $json.level_number }}"
            }
          ]
        },
        "tableId": "workflow_levels",
        "operation": "get"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "68732d0b-c579-45dd-90b5-022bacccd8c3",
      "name": "get_user_by_role1",
      "type": "n8n-nodes-base.supabase",
      "position": [
        80,
        1440
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "role_id",
              "keyValue": "={{ $json.role_id }}",
              "condition": "eq"
            }
          ]
        },
        "tableId": "users",
        "operation": "getAll",
        "returnAll": true
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "4075c718-7f9d-41ef-a8d9-aad892838493",
      "name": "generate_uuid",
      "type": "n8n-nodes-base.crypto",
      "position": [
        416,
        1440
      ],
      "parameters": {
        "action": "generate"
      },
      "typeVersion": 1
    },
    {
      "id": "4c8bac58-805f-4a43-92a0-ebfde03c5092",
      "name": "create_approval_record",
      "type": "n8n-nodes-base.supabase",
      "position": [
        800,
        1456
      ],
      "parameters": {
        "tableId": "approvals",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "document_id",
              "fieldValue": "={{ $('get_approval_data').item.json.document_id }}"
            },
            {
              "fieldId": "level_id",
              "fieldValue": "={{ $('get_next_level').item.json.id }}"
            },
            {
              "fieldId": "approver_id",
              "fieldValue": "={{ $json.id }}"
            },
            {
              "fieldId": "token",
              "fieldValue": "={{ $json.data }}"
            },
            {
              "fieldId": "status",
              "fieldValue": "=Pending"
            },
            {
              "fieldId": "expiry_time",
              "fieldValue": "={{ new Date(Date.now() + 48 * 60 * 60 * 1000) }}"
            }
          ]
        }
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "ebd1975c-a8c6-4703-89a0-9eb062aae079",
      "name": "send_emai_by_level",
      "type": "n8n-nodes-base.gmail",
      "position": [
        -560,
        2032
      ],
      "parameters": {
        "sendTo": "={{ $('generate_uuid').item.json.email }}",
        "message": "=<p>Please review:</p>\n<p>\n  <a href=\"http://localhost:5678/webhook-test/approve?token={{ $('generate_uuid').item.json.data }}&decision=approved\">Approve</a> |\n  <a href=\"http://localhost:5678/webhook-test/approve?token={{ $('generate_uuid').item.json.data }}&decision=rejected\">Reject</a>\n</p>",
        "options": {
          "attachmentsUi": {
            "attachmentsBinary": [
              {}
            ]
          }
        },
        "subject": "=Document Approval Request - {{ $('get_document_details').item.json.title }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "40dcfb0b-0c3f-4469-a3ba-c85793c1da1b",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1312,
        -240
      ],
      "parameters": {
        "width": 608,
        "height": 2528,
        "content": "## Multi-Level Document Approval & Audit Workflow\n\nThis workflow automates a **document approval process** using Supabase and Gmail.  \n\n---\n\n### Who it\u2019s for\n- Teams that need structured multi-level document approvals.  \n- Companies managing policies, contracts, or proposals.  \n- Anyone using **Supabase** as a backend with approval/audit requirements.  \n\n---\n\n### How it works\n1. **Form Trigger** \u2013 A user submits a document via the form.  \n2. **Supabase Integration** \u2013 The document is saved in the `documents` table.  \n3. **Workflow Levels** \u2013 Fetches the correct approval level from `workflow_levels`.  \n4. **Assign Approvers** \u2013 Matches approvers by role from the `users` table.  \n5. **Approval Record** \u2013 Creates an `approvals` record with a unique token and expiry.  \n6. **Email Notification** \u2013 Sends an email with **Approve / Reject links**.  \n7. **Audit Logs** \u2013 Records every approval request in `audit_logs`.  \n\n---\n\n### How to set up\n- Configure your **Supabase credentials**.  \n- Update table IDs (`documents`, `workflow_levels`, `users`, `approvals`, `audit_logs`) to match your schema.  \n- Connect your **Gmail account**.  \n- Adjust approval expiry time (`48h` default).  \n- Deploy and test via the **Form Trigger**.  \n\n---\n\n### Requirements\n- A Supabase project with the listed tables.  \n- A Gmail account connected to n8n.  \n\n---\n\n### Customization\n- Add multiple approval levels by chaining `workflow_levels`.  \n- Replace Gmail with Slack, Teams, or another notification channel.  \n- Adjust audit logging for compliance needs.  \n- Update the endpoint - http://localhost:5678/webhook-test/ based on instance and env (remove test if you run in prod)\n- Handle error in each step pf db interaction.\n\n---\n\n### 1. **Webhook Entry Point**\n- Triggered when an approver clicks the **Approve** or **Reject** link in email.  \n- Captures query parameters:  \n  - `token` (approval token)  \n  - `decision` (approved/rejected)  \n\n---\n\n### 2. **Approval Data Retrieval & Update**\n- Fetch approval record from **Supabase (approvals)** using `token`.  \n- Update approval status:  \n  - `Approved` \u2192 moves to next workflow level or final approval.  \n  - `Rejected` \u2192 document marked as rejected immediately.  \n- Records `acted_at` timestamp.  \n\n---\n\n### 3. **Decision Check**\n- **IF Node** checks whether the decision is **approved** or **rejected**.  \n- **Reject Path** \u2192 Update document status to **Rejected** in `documents`.  \n- **Approve Path** \u2192 Continue workflow level progression.  \n\n---\n\n### 4. **Workflow Level Progression**\n- Fetch details of the current workflow level.  \n- Identify the **next level** (`workflow_levels`) based on `level_number`.  \n\n#### \u2705 If Next Level Exists:\n- Retrieve approvers by `role_id`.  \n- Generate unique approval tokens.  \n- Create new approval records in `approvals`.  \n- Send **email notifications** with approval/reject links.  \n\n#### \u274c If No Next Level (Last Level):\n- Update document status to **Approved** in `documents`.  \n\n---\n\n### 5. **Audit Logging**\n- Every approval action is logged into `audit_logs` table:  \n  - `document_id`  \n  - `action` (e.g., `approval_sent`, `approved`, `rejected`)  \n  - `actor_email` (system/approver)  \n  - `details` (workflow level, role info, etc.)  \n\n---\n\n## \ud83d\udce8 Email Template\nApproval request email includes **decision links**:  \n\n```html\n<p>Please review the document:</p>\n<p>\n  <a href=\"http://localhost:5678/webhook-test/doc-approval?token={{$json.token}}&decision=approved\">\u2705 Approve</a> |\n  <a href=\"http://localhost:5678/webhook-test/doc-approval?token={{$json.token}}&decision=rejected\">\u274c Reject</a>\n</p>'''\n"
      },
      "typeVersion": 1
    },
    {
      "id": "7db49d0e-c7c5-4423-af60-17e63aa9fea1",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -656,
        -224
      ],
      "parameters": {
        "width": 720,
        "height": 1120,
        "content": "## Database Schema\n\n```sql\n-- 1. ROLES: Define roles like Manager, Finance, HR\nCREATE TABLE roles (\n    id SERIAL PRIMARY KEY,\n    name VARCHAR(100) NOT NULL UNIQUE,\n    description TEXT\n);\n\n-- 2. USERS: All approvers (internal + external flag)\nCREATE TABLE users (\n    id SERIAL PRIMARY KEY,\n    name VARCHAR(150) NOT NULL,\n    email VARCHAR(200) NOT NULL UNIQUE,\n    role_id INT REFERENCES roles(id) ON DELETE SET NULL,\n    is_external BOOLEAN DEFAULT FALSE,\n    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n);\n\n-- 3. DOCUMENTS: The items that need approval\nCREATE TABLE documents (\n    id SERIAL PRIMARY KEY,\n    title VARCHAR(255) NOT NULL,\n    content TEXT, -- could also just store metadata, file path, or S3 link\n    submitted_by INT REFERENCES users(id) ON DELETE SET NULL,\n    status VARCHAR(50) DEFAULT 'Pending', -- Pending / Approved / Rejected\n    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n);\n\n-- 4. WORKFLOW LEVELS: Configure levels & roles\nCREATE TABLE workflow_levels (\n    id SERIAL PRIMARY KEY,\n    level_number INT NOT NULL,\n    role_id INT REFERENCES roles(id) ON DELETE CASCADE,\n    approval_type VARCHAR(20) DEFAULT 'any', -- any / all\n    description TEXT\n);\n\n-- 5. APPROVALS: Tracks individual approval actions\nCREATE TABLE approvals (\n    id SERIAL PRIMARY KEY,\n    document_id INT REFERENCES documents(id) ON DELETE CASCADE,\n    level_id INT REFERENCES workflow_levels(id) ON DELETE CASCADE,\n    approver_id INT REFERENCES users(id) ON DELETE CASCADE,\n    token VARCHAR(255) NOT NULL UNIQUE, -- one-time token for secure link\n    status VARCHAR(20) DEFAULT 'Pending', -- Pending / Approved / Rejected\n    expiry_time TIMESTAMP,\n    acted_at TIMESTAMP\n);\n\n-- 6. AUDIT LOGS (optional, for tracking history)\nCREATE TABLE audit_logs (\n    id SERIAL PRIMARY KEY,\n    document_id INT REFERENCES documents(id) ON DELETE CASCADE,\n    action VARCHAR(50), -- submitted / approved / rejected / escalated\n    actor_email VARCHAR(200),\n    details TEXT,\n    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n);\n```"
      },
      "typeVersion": 1
    },
    {
      "id": "25ef7fca-6462-4806-bf01-d0c552aabae7",
      "name": "Audit",
      "type": "n8n-nodes-base.supabase",
      "position": [
        416,
        1792
      ],
      "parameters": {
        "tableId": "audit_logs",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "document_id",
              "fieldValue": "={{ $('get_approval_data').item.json.document_id }}"
            },
            {
              "fieldId": "action",
              "fieldValue": "approval_sent"
            },
            {
              "fieldId": "actor_email",
              "fieldValue": "system@workflow"
            },
            {
              "fieldId": "details",
              "fieldValue": "=Level {{ $('get_next_level').item.json.level_number }}  requests sent to role_id {{ $('generate_uuid').item.json.role_id}} "
            }
          ]
        }
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "48036695-12b4-479a-a547-eb45eb9da598",
      "name": "Respond to Webhook1",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1552,
        2016
      ],
      "parameters": {
        "options": {},
        "respondWith": "text",
        "responseBody": "=Workflow Competed - {{ $json.Response }}"
      },
      "typeVersion": 1.4
    },
    {
      "id": "d2c8dca0-c040-4035-bbd2-5812e571e0b9",
      "name": "upload_to_supabase_storage",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        464,
        0
      ],
      "parameters": {
        "url": "=https://<your_project_id>.supabase.co/storage/v1/object/test-n8n/{{ $binary.data.fileName }}",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "binaryData",
        "authentication": "predefinedCredentialType",
        "inputDataFieldName": "data",
        "nodeCredentialType": "supabaseApi"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "86e2bbb7-44b6-43f7-bf31-28453caf3369",
      "name": "fetch_file_to_review",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        432,
        464
      ],
      "parameters": {
        "url": "=https://uptttiuxuaacxrdofqgm.supabase.co/storage/v1/object/{{ $('upload_to_supabase_storage').item.json.Key }}",
        "options": {},
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "supabaseApi"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "c82dba30-479d-4045-af9d-635f1aea605b",
      "name": "get_document_details",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1168,
        1456
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "id",
              "keyValue": "={{ $json.document_id }}"
            }
          ]
        },
        "tableId": "documents",
        "operation": "get"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "13d7e82a-f7b3-4cbd-b51f-bcc1e57a1602",
      "name": "fetch_file_to_review1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1536,
        1456
      ],
      "parameters": {
        "url": "=https://<your_project_id>.supabase.co/storage/v1/object/test-n8n/{{ $json.content }}",
        "options": {},
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "supabaseApi"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "db503b96-a362-4b14-a41b-aa87bf156392",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        80,
        1104
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "eff8437b-ef76-4bef-a6c2-9d65083ab8c5",
              "operator": {
                "type": "object",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{ $json }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "694b4cde-a457-4496-816f-02ba86b4eb9e",
      "name": "response_message",
      "type": "n8n-nodes-base.set",
      "position": [
        800,
        1296
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "d6c443be-ca83-4708-b80b-9a5eefd11d60",
              "name": "Response",
              "type": "string",
              "value": "Not a value token"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "30cd5073-3d59-48ae-a572-57157ee5e6cb",
      "name": "response_message1",
      "type": "n8n-nodes-base.set",
      "position": [
        800,
        1792
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "d6c443be-ca83-4708-b80b-9a5eefd11d60",
              "name": "Response",
              "type": "string",
              "value": "Rejected"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "17e8d16b-8c04-45de-90a0-1d8fc1711cd5",
      "name": "response_message2",
      "type": "n8n-nodes-base.set",
      "position": [
        128,
        2032
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "d6c443be-ca83-4708-b80b-9a5eefd11d60",
              "name": "Response",
              "type": "string",
              "value": "Approved"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "bb9fb0aa-d3a2-434b-a34a-047562654983",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        352,
        -128
      ],
      "parameters": {
        "width": 336,
        "height": 288,
        "content": "### Update url for supabase storage "
      },
      "typeVersion": 1
    },
    {
      "id": "d902be56-14a6-4071-ae13-7b0dddf4284a",
      "name": "end_form",
      "type": "n8n-nodes-base.form",
      "position": [
        1472,
        464
      ],
      "parameters": {
        "options": {},
        "operation": "completion",
        "completionTitle": "Approval Workflow Started."
      },
      "typeVersion": 1
    },
    {
      "id": "edf83e23-536a-4a9d-a5be-f6401690ab2a",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        112,
        -208
      ],
      "parameters": {
        "color": 4,
        "width": 1664,
        "height": 1120,
        "content": "## Form Submit flow"
      },
      "typeVersion": 1
    },
    {
      "id": "5109e9e9-b938-44be-8154-7dd287030589",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -656,
        992
      ],
      "parameters": {
        "color": 4,
        "width": 2448,
        "height": 1264,
        "content": "## Next Level Approval"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "de5c52a4-7369-4d59-a8c1-b7e4e1aa5636",
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "update_approval_data",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "response_message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Audit": {
      "main": [
        [
          {
            "node": "response_message1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Audit1": {
      "main": [
        [
          {
            "node": "response_message2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook": {
      "main": [
        [
          {
            "node": "get_approval_data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "send_email": {
      "main": [
        [
          {
            "node": "audit_invites",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "audit_invites": {
      "main": [
        [
          {
            "node": "end_form",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "generate_uuid": {
      "main": [
        [
          {
            "node": "create_approval_record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "is_last_level": {
      "main": [
        [
          {
            "node": "get_workflow_by_level",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Final Update Document",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "save_document": {
      "main": [
        [
          {
            "node": "get_workflow_level_one",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "get_next_level": {
      "main": [
        [
          {
            "node": "is_last_level",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "get_user_by_role": {
      "main": [
        [
          {
            "node": "create_uuid_token",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "response_message": {
      "main": [
        [
          {
            "node": "Respond to Webhook1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "create_uuid_token": {
      "main": [
        [
          {
            "node": "create_record_approvals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "get_approval_data": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "get_level_details": {
      "main": [
        [
          {
            "node": "get_next_level",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "get_user_by_role1": {
      "main": [
        [
          {
            "node": "generate_uuid",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "response_message1": {
      "main": [
        [
          {
            "node": "Respond to Webhook1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "response_message2": {
      "main": [
        [
          {
            "node": "Respond to Webhook1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "send_emai_by_level": {
      "main": [
        [
          {
            "node": "Audit1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "start_approval_form": {
      "main": [
        [
          {
            "node": "upload_to_supabase_storage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "fetch_file_to_review": {
      "main": [
        [
          {
            "node": "send_email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "get_document_details": {
      "main": [
        [
          {
            "node": "fetch_file_to_review1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "update_approval_data": {
      "main": [
        [
          {
            "node": "check_reject_or_approve",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Final Update Document": {
      "main": [
        [
          {
            "node": "Audit",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "fetch_file_to_review1": {
      "main": [
        [
          {
            "node": "send_emai_by_level",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "get_workflow_by_level": {
      "main": [
        [
          {
            "node": "get_user_by_role1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "create_approval_record": {
      "main": [
        [
          {
            "node": "get_document_details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "get_workflow_level_one": {
      "main": [
        [
          {
            "node": "get_user_by_role",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "check_reject_or_approve": {
      "main": [
        [
          {
            "node": "get_level_details",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Final Update Document",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "create_record_approvals": {
      "main": [
        [
          {
            "node": "fetch_file_to_review",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "upload_to_supabase_storage": {
      "main": [
        [
          {
            "node": "save_document",
            "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 workflow automates a document approval process using Supabase and Gmail. Teams that need structured multi-level document approvals. Companies managing policies, contracts, or proposals. Medical document need multiple lavel of review and approval. Form Trigger – A user…

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

More Email & Gmail workflows → · Browse all categories →

Related workflows

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

Email & Gmail

🎥 Analyze YouTube Video for Summaries, Transcripts & Content + Google Gemini AI. Uses stickyNote, httpRequest, googleDrive, gmail. Event-driven trigger; 33 nodes.

HTTP Request, Google Drive, Gmail +2
Email & Gmail

Wait. Uses httpRequest, itemLists, slack, gmail. Webhook trigger; 29 nodes.

HTTP Request, Item Lists, Slack +2
Email & Gmail

Splitout Extractfromfile. Uses splitOut, httpRequest, formTrigger, form. Event-driven trigger; 21 nodes.

HTTP Request, Form Trigger, Form +1
Email & Gmail

With this template, users will be able to automate design and marketing tasks such as creating variants of existing designs, remixing existing assets to validate different styles and explore a range o

HTTP Request, Form Trigger, Form +1
Email & Gmail

ASO Analyzer. Uses formTrigger, httpRequest, openAi, googleSheets. Event-driven trigger; 17 nodes.

Form Trigger, HTTP Request, OpenAI +3