An approval workflow is the most reusable pattern in business automation. Build it once for expense reports and you have the template for purchase requisitions, time-off requests, vendor onboarding approvals, and any other process that requires a human decision before something moves forward.

This tutorial builds a complete approval workflow in n8n: a submission form, amount-based routing to the right approver, a notification with one-click approve or reject, and an automatic follow-up if no response comes within the defined window.

What You Are Building

A reusable n8n approval workflow that:

  1. Accepts a submission via form or webhook
  2. Routes the request to the correct approver based on defined rules (amount, category, or department)
  3. Sends the approver a notification with approve and reject links
  4. Waits for the approver's response
  5. Executes the approved action or returns the rejection to the requester
  6. Escalates automatically if the approver does not respond within the defined window

The tutorial uses expense report approval as the example, but every node maps directly to purchase requisitions or any other approval use case.

Prerequisites

n8n instance with version 1.0 or later. This workflow uses n8n's built-in Form Trigger and Wait node, both available in standard n8n.

Email or Slack for notifications. The tutorial uses email (Gmail or SMTP). If you prefer Slack, the notification node swaps in with the same logic.

A destination system for approved records. This could be Google Sheets (simple), Airtable, or an ERP via API. The tutorial shows Google Sheets as the write target, with notes on adapting to an ERP API at the end.

Defined approval rules. Before building, document: who approves what amounts, what the escalation path is if they do not respond, and what happens on rejection. The workflow cannot route what has not been defined.

Workflow Overview

n8n Form Trigger (submission)

    → Switch node (route by amount)

        → Branch A: Auto-approve (under $100)

        → Branch B: Manager approval ($100-$500)

        → Branch C: Director approval (over $500)

    → Send Approval Email (with approve/reject links)

    → Wait node (hold for response, max 24 hours)

    → IF node (approved or rejected)

        → Approved: Write to Google Sheets, notify requester

        → Rejected: Notify requester with reason

    → (Parallel) Schedule: Escalate if no response in 24 hours

Step-by-Step Build

Step 1: Set Up the Form Trigger

In n8n, add an n8n Form Trigger node as the starting point. This creates a hosted form your team can submit from any browser.

Configure the form fields:

  • Requester Name (text)
  • Requester Email (email)
  • Description (text)
  • Amount (number)
  • Category (dropdown: Travel, Supplies, Equipment, Other)
  • Receipt Attached? (checkbox)

Click the form preview link to confirm the form renders correctly. Copy the production form URL: this is what you will share with your team.

For more complex deployments, you can replace the Form Trigger with a Webhook node and build the form in Retool or Tally. The rest of the workflow is identical.

Step 2: Add a Switch Node for Approval Routing

Add a Switch node after the form trigger. This routes the submission to the correct approval branch based on the amount.

Configure three outputs:

  • Output 1 (Auto-approve): Amount less than 100
  • Output 2 (Manager): Amount greater than or equal to 100 AND less than or equal to 500
  • Output 3 (Director): Amount greater than 500

In the Switch node, use the expression {{ $json.Amount }} to reference the submitted amount. Adjust the thresholds to match your actual approval matrix.

Step 3: Handle Auto-Approvals

Connect Output 1 (under $100) directly to the approval action without a notification step. Add a Google Sheets node to log the approved record, then add a Gmail node to send the requester a confirmation.

Auto-approvals should still be logged. If an expense is automatically approved and later questioned, you need the record.

Step 4: Build the Approval Email

For the Manager and Director branches, add a Gmail node configured to send an approval request.

The email should contain:

  • The submission details (requester, amount, description, category)
  • An Approve link (this is an n8n webhook URL that triggers the approval branch)
  • A Reject link (this is a separate n8n webhook URL that triggers the rejection branch)

To generate these links, you will use n8n's Wait node in the next step. Build a placeholder email first, then update the links once the Wait node is configured.

A clean subject line format: Approval Required: [Category] expense for $[Amount], [Requester Name]

Step 5: Add the Wait Node

The Wait node pauses the workflow until one of two things happens: the approver clicks a link, or the timeout expires.

Add a Wait node after the Gmail send. Configure it:

  • Resume: On webhook call
  • Limit wait time: Enable, set to 24 hours

The Wait node generates two webhook URLs automatically: one for resuming when called. You will create two separate webhook paths for approve and reject by using the Wait node's resume URL with a query parameter to indicate the decision.

A simpler approach for this tutorial: create two separate workflows: one that handles the "approved" callback and one that handles the "rejected" callback - and link to each from the email. Each callback workflow writes to the appropriate destination and notifies the requester. This avoids the complexity of query parameter parsing while keeping the logic clean.

Step 6: Handle the Approved Path

In the approved callback workflow (triggered when the approver clicks Approve):

  • Add a Google Sheets node to write the approved record to your expense log
  • Add a Gmail node to notify the requester: "Your expense report for $[Amount] has been approved."
  • If your accounting system has an API, replace or supplement the Sheets write with an HTTP Request node to create the expense record directly

Step 7: Handle the Rejected Path

In the rejected callback workflow (triggered when the approver clicks Reject):

  • Add a Gmail node to notify the requester with the rejection
  • Include the approver's name and a standard message asking the requester to revise and resubmit
  • Log the rejection in Google Sheets as well, with a status of "Rejected"

Step 8: Set Up the Escalation

For the escalation case (approver does not respond within 24 hours), add a separate workflow triggered by a schedule. This workflow:

  • Reads the pending approvals log from Google Sheets
  • Checks the submission timestamp against the current time
  • For any submission pending more than 24 hours, sends an escalation email to the approver's manager

This keeps the main approval workflow clean while ensuring nothing sits indefinitely.

What to Watch Out For

Approvers clicking links multiple times. If the approver clicks Approve twice, the Google Sheets write may duplicate. Add a check in the approved workflow to see if the record has already been processed before writing.

Thresholds changing over time. The Switch node thresholds are hardcoded. Document them in the workflow notes and set a reminder to review them quarterly. If your approval matrix changes frequently, consider reading the thresholds from a Google Sheet so they can be updated without editing the workflow.

No rejection reason captured. The basic tutorial sends the approver directly to a URL. If you want to capture a rejection reason, replace the direct link with a short form (a second n8n Form Trigger) that asks for the reason before triggering the rejection path.

Adapting This for Purchase Requisitions

The same workflow applies to purchase requisitions with two changes:

  1. Form fields change (item, vendor, quantity, estimated cost, preferred delivery date)
  2. The approved action changes: instead of writing to an expense log, you add an HTTP Request node to create the PO in your ERP via API

Every other node is identical. The approval routing, wait logic, escalation, and notification structure transfers directly.

The Flow Kaizen guide covers how to document your approval matrix before building, the most common reason approval workflows require multiple rounds of revision is that the rules were not defined before the build started.