
n8n Purchase Request Approval: Build a PO Intake Workflow With Human Review
TL;DR: Purchase request approval is a clean first workflow for approval control in n8n. The workflow can capture the request, classify vendor, amount, department, and urgency, then pause before anything is written downstream. The hard part is not the approval button. It is queue, owner, deadline, decision, escalation, and audit trail.
Purchase requests are a good test for n8n approval workflows because they sit in the awkward middle of back-office automation.
They are structured enough to automate. Someone asks for a laptop refresh, design contractor, software license, office equipment, or vendor renewal. The request has a requester, department, amount, business reason, urgency, attachments, and often a budget owner.
They are also risky enough that you usually do not want the workflow to run straight through. A human still needs to check whether the request is real, whether the amount is sane, whether the vendor is approved, whether the budget owner has context, and whether the next system should receive a PO draft, a task, a spreadsheet row, or nothing.
That is the wedge for Humangent:
Human approval control for n8n workflows.
This post walks through a purchase request / PO intake workflow in n8n, where the automation does the intake and preparation, but the approval state lives somewhere your team can actually run it.
The workflow shape
The simple version looks like this:
[Gmail / Form / Slack request intake]
-> [Normalize fields]
-> [Classify request type, vendor, amount, urgency]
-> [Look up requester, department, budget owner]
-> [Create approval request]
-> [Wait for human decision]
-> [Branch on approved / edited / rejected / escalated]
-> [Write approved result downstream]
The key decision is where approval state lives.
If this is one workflow with one reviewer, n8n's built-in Send and Wait for Response can be enough. If purchase requests are one of several operational workflows, and different people own different request types, the approval state needs a stronger shape:
- queue
- owner
- deadline
- decision
- escalation
- audit trail
Without those, the workflow may still run, but the team has no real operating surface.
Intake: capture the request
Start with whichever intake channel your team already uses:
- A Google Form for structured requests
- A shared mailbox like
[email protected] - A Slack workflow button
- An internal tool webhook
- A spreadsheet row created by another process
The intake does not need to be perfect. It needs to capture enough for n8n to normalize the request into one object:
{
"request_id": "pr_4827",
"requester_email": "[email protected]",
"department": "Operations",
"request_type": "equipment",
"vendor_name": "Apple",
"amount": 4820,
"currency": "USD",
"business_reason": "Laptop refresh for three field ops hires",
"urgency": "this_week",
"attachments": ["quote.pdf"],
"requested_at": "2026-04-30T09:14:00Z"
}
If the request comes from email, use an LLM extraction step carefully. Treat the extraction as a draft, not truth. The reviewer should be able to correct the vendor, amount, department, or business reason before approving.
Enrichment: decide who owns it
Before routing, n8n should enrich the request with the context a reviewer needs:
- Requester profile and department
- Budget owner
- Vendor status: known, new, blocked, missing tax details
- Amount tier
- Existing open requests from the same department or vendor
- Required approval levels
A simple amount policy might look like this:
amount < 500 -> team lead
amount < 5000 -> team lead + budget owner
amount >= 5000 -> team lead + budget owner + finance
new vendor -> add admin review
missing attachment -> route back to requester
That policy can live in a Google Sheet, Airtable table, Postgres table, or static config in n8n while you are validating the workflow. The important part is that routing rules are explicit. "Post to #ops and hope someone sees it" is not routing.
Approval: pause before the downstream write
The approval request should show the reviewer:
- Request summary
- Extracted fields
- Attachments or source message
- Amount tier and routing reason
- Any missing or suspicious fields
- Available actions
Useful actions are usually more than approve and reject:
{
"actions": [
"approve",
"approve_with_edits",
"reject",
"request_more_info",
"escalate_to_finance"
]
}
Approve-with-edits matters. If the amount was extracted as $4,820 but the updated quote is $4,720, the reviewer should fix it once, approve, and send the corrected value downstream. A binary approve/reject step turns every small correction into a manual side conversation.
Three implementation patterns
Pattern 1: Send and Wait for a simple first version
For a first version, use n8n's native Send and Wait for Response on Slack, Gmail, or Teams.
[Normalize request]
-> [Slack: Send and Wait for Response]
Response type: Custom Form
Fields: vendor, amount, business_reason, decision, notes
Limit wait time: 24h
-> [Switch on decision]
approve -> create downstream row
reject -> notify requester
request_more_info -> email requester
timeout -> notify backup reviewer
This is the right place to start if:
- one person owns approvals
- volume is low
- you do not need cross-workflow visibility
- the audit trail can be a spreadsheet row plus n8n execution history
It stops being enough when the same people review requests from several workflows, when deadlines matter, or when the team lead needs to see what is pending without opening n8n.
Pattern 2: Database-backed request state
The next step is a purchase_requests table and a small state machine:
CREATE TABLE purchase_requests (
id TEXT PRIMARY KEY,
requester_email TEXT NOT NULL,
department TEXT,
request_type TEXT,
vendor_name TEXT,
amount NUMERIC(12,2),
currency TEXT,
status TEXT NOT NULL,
owner_email TEXT,
deadline_at TIMESTAMP,
approved_payload JSONB,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE purchase_request_events (
id TEXT PRIMARY KEY,
request_id TEXT REFERENCES purchase_requests(id),
actor TEXT,
event_type TEXT,
data JSONB,
created_at TIMESTAMP DEFAULT NOW()
);
Now n8n can run separate workflows:
- intake workflow creates the request row
- routing workflow assigns owner and deadline
- notification workflow pings the reviewer
- callback workflow records the decision
- downstream workflow creates the PO draft or system record
This gives you a real queue and audit trail, but you are now maintaining an internal approval product. For many small teams, that is too much product for a request workflow.
Pattern 3: Approval control outside the canvas
The Humangent direction is to keep n8n focused on automation and move approval control into a purpose-built layer.
[Normalize + enrich purchase request]
-> [HTTP Request: POST to Humangent]
callback_url: n8n Wait for Webhook URL
title: "Purchase request: laptop refresh ($4,820)"
assignee: "ops-team-lead"
deadline: "24h"
fields: vendor, amount, department, reason
editable_fields: vendor, amount, reason
actions: approve, reject, request_more_info, escalate
-> [Wait for Webhook]
-> [Switch on Humangent decision]
-> [Write approved payload downstream]
The point is not to replace n8n. The point is to keep the approval state from being reimplemented in every workflow.
Humangent is pre-launch and in private beta. The product direction is human approval control for n8n workflows: queue, owner, deadline, decision, and audit trail before n8n writes into another system.
Downstream writes: only approved data moves
After approval, n8n writes the approved payload to the downstream system:
- Google Sheets or Airtable for an early ops process
- Linear, Jira, or ClickUp for internal tasks
- ERP/procurement system for mature purchase processes
- Slack notification for the requester
- Email to vendor or budget owner
The downstream write should use the reviewed values, not the originally extracted values.
That sounds obvious, but it is a common approval-flow bug. The reviewer edits the amount in the approval form, but the later node still reads from the original extraction node. In n8n, name the approved payload clearly and branch from that object:
approved_payload.amount
approved_payload.vendor_name
approved_payload.business_reason
approved_payload.decision_note
What the audit trail should record
For purchase requests, a useful audit trail is simple:
- request created
- owner assigned
- reviewer opened request
- reviewer edited fields
- reviewer approved, rejected, requested more info, or escalated
- timeout or escalation fired
- downstream write completed
The record should answer:
- Who approved this?
- What was changed before approval?
- Which policy routed it?
- Was it escalated?
- What did n8n write downstream?
That is the difference between "the workflow ran" and "the team can defend the decision."
Common mistakes
Using Slack as the queue. Slack is fine as a notification channel. It is a bad source of truth for pending purchase requests. Messages drift, owners are implicit, and audit is search.
Skipping editable fields. Extraction errors are normal. If reviewers cannot correct fields before approving, small mistakes become reject-and-retry loops.
Auto-approving on timeout. For purchase requests, silence should escalate or hold. Auto-approval is usually the wrong default.
Writing downstream before approval. Do not create a PO draft, ERP record, or vendor task until the approval decision exists. The approval should gate the write.
Letting invoice approval become the wedge. Invoice approval is valuable, but many finance platforms already own that workflow. Purchase request / PO intake is a cleaner early use case for teams that already use n8n and still run requests through email, Slack, and spreadsheets.
Related guides
- How to build an n8n approval workflow — the general three-pattern overview
- n8n Slack approval workflow — why Slack is a channel, not approval state
- n8n approval timeouts and escalation — what happens when reviewers do not respond
- How to build multi-level approval workflows in n8n — sequential sign-offs across roles
- Every human decision in n8n needs a record — the audit trail requirement
If your team has automated purchase request intake in n8n but approvals still live in Slack, email, or spreadsheets, Humangent is being built as human approval control for n8n workflows: every request gets a queue, owner, deadline, decision, and audit trail before n8n writes into another system. Join the waitlist at humangent.io. Free during private beta, no credit card.