Skip to content
Notifications
Clear all

Guide: Setting up custom approval workflows for budget sign-offs

1 Posts
1 Users
0 Reactions
3 Views
(@tool_tinkerer)
Eminent Member
Joined: 2 months ago
Posts: 16
Topic starter   [#1077]

I've been working on a project where any departmental budget request over $5k needs a dual-layer approval: first the department head, then a finance controller. Our finance team was drowning in emails and spreadsheets, so I built a custom approval chain using n8n.

The core idea is to trigger the workflow from our project management tool (we use ClickUp), handle the approval steps sequentially with logic gates, and then sync the final decision back. Here's a simplified version of the main flow:

```json
{
"nodes": [
{
"name": "ClickUp - New Budget Task",
"type": "n8n-nodes-base.clickUpTrigger"
},
{
"name": "Extract Amount & Requester",
"type": "n8n-nodes-base.code",
// Extracts custom field values for decision logic
},
{
"name": "Approval Step 1 - Dept Head",
"type": "n8n-nodes-base.emailSend",
// Sends approval request with link to a simple webform
},
{
"name": "Wait for First Response",
"type": "n8n-nodes-base.webhook",
// Waits for the webform response or times out
},
{
"name": "Check First Approval",
"type": "n8n-nodes-base.if",
"conditions": {
"options": {},
"conditions": [{
"leftValue": "={{ $json.approval_1 }}",
"operator": "equal",
"rightValue": "approved"
}]
}
},
{
"name": "Approval Step 2 - Finance",
"type": "n8n-nodes-base.microsoftTeams",
// Sends message to Finance channel, only if first step passes
}
]
}
```

Key considerations I ran into:
* **State Management:** You need a way to "pause" the workflow and resume it when an approver acts. I used a dedicated webhook node for this, storing the execution ID.
* **Timeouts & Escalations:** Every approval step needs a timeout (e.g., 48 hours). If the first approver doesn't respond, the workflow escalates to their deputy.
* **Audit Trail:** Every decision is logged back to the original ClickUp task as a comment, and a separate Google Sheet row is appended for finance records.

The main pitfall is overcomplicating the rejection logic. Initially, I had separate paths for rejections at each stage, but it was cleaner to route all "rejected" outcomes to a single node that handles notifications and status updates.

For simpler setups, you could replicate this in Zapier using a combination of Delay by Zapier (for timeouts) and Paths for the conditional logic, though the visual branching gets messy after two approval layers.

What approval systems are you all using? Have you found a cleaner way to handle the pause-and-resume pattern?


if it's manual, it's wrong


   
Quote