Part 1 has the contents list of every section and case study.
Case studies in full
AI-Powered Construction Report SaaS (MeinBüromeister)
Turning construction-site voice notes, photos, and messages into structured reports through an automated AI-powered backend for German trade companies.
Section: Custom SaaS Platforms
Overview
MeinBüromeister is a B2B SaaS platform for German construction and trade companies. It allows workers to submit job updates through WhatsApp instead of preparing every report manually. The backend organizes incoming information, generates structured reports, and asks workers to review them before submission.
The Business Problem
Construction workers often send separate voice notes, photos, and text corrections from job sites. Office staff must identify the correct customer and project, organize materials and working hours, and format the information into professional reports. This creates repetitive administrative work and makes report preparation more time-consuming. The goal was to reduce this manual effort while keeping workers involved in reviewing and approving their reports.
The Solution
An n8n-based backend receives WhatsApp messages and groups related inputs into a single session. OpenAI Whisper transcribes voice recordings, while Claude AI extracts relevant report information into structured data. After the worker reviews and approves the report, the backend stores it in Supabase for delivery to the office dashboard. Supporting workflows automate customer onboarding, subscription management, team access, and error handling.
Project Snapshot
A production backend connecting WhatsApp messaging, AI-powered report extraction, worker approval, report storage, customer onboarding, and subscription lifecycle management.
How the System Works
System Architecture
The backend is organized around an n8n automation layer that sits between WhatsApp, the AI services used for transcription and extraction, and the Supabase/Stripe infrastructure that powers the office dashboard.
Supporting Integrations
Stripe: Checkout, subscription lifecycle events, plan changes, and subscription-based access rules.
Supabase Auth: Authentication support for the application.
Supabase Storage: Storage for uploaded photos and other media.
Docker: Supports the self-hosted deployment environment.
Core Automation Workflows
The backend is built around interconnected n8n workflows that automate WhatsApp message handling, AI-powered report generation, customer onboarding, and subscription management. Each workflow handles a specific responsibility and integrates with the relevant APIs and backend services to support the complete reporting lifecycle. Some main automation workflows are shown below.
1. Core Onboarding & Workflow Management
This workflow handles company onboarding, setup-code verification, worker registration, subscription checks, report approval, project management, and notifications through interconnected n8n automation nodes.
Image: Core onboarding and workflow management: company setup, worker registration, subscription checks, report approval, project handling, and notifications across 15 interconnected automation groups.
2. AI-Powered Report Processing Workflow
This workflow processes WhatsApp messages using Whisper and Claude AI to extract structured report data, enrich customer and project details, validate reports, and handle database updates and notifications.
Image: AI-powered report processing: message intake, voice transcription, Claude-based data extraction, report generation, and save/notification handling.
Product Experience
Report inbox
Image: The office inbox organizes incoming reports by date, technician, customer/project, category, and status.
Customers and projects
Image: The project view groups customers and highlights open-report counts and recent work.
WhatsApp work history
Image: Workers review and approve each AI-generated report directly in WhatsApp before it goes to the office.
<30s: Voice note to structured report
Image: Once approved, the report is saved, confirmed back to the worker on WhatsApp, and delivered to the office as a PDF.
Core Backend Capabilities
AI Report Extraction: Supports four report categories (Rapport, Aufmaß, Neues Angebot, and Notiz). The AI extracts work descriptions, materials, dimensions, and working hours while using prompt guardrails to reduce invented details.
Multi-Input Session Handling: Groups related voice notes, photos, captions, and corrections into a single processing session instead of treating every incoming message as a separate report.
Project Matching and Clarification: Uses available employee and project records to associate reports with the correct destination. When a match is ambiguous, the workflow can request clarification.
Onboarding and Access Management: Supports company setup, worker invitations, registration tracking, and access checks to ensure incoming messages are routed correctly.
Subscription Lifecycle Management: Handles relevant Stripe events and subscription states, including active, canceling, and canceled subscriptions. It also manages plan mapping and seat limits.
Failure Handling and Validation: Validates incoming data and AI-generated output, handles incomplete sessions and invalid actions, and provides controlled paths for processing failures.
Results & Metrics
5: Production workflows
5: Testing rounds
30+: Test scenarios per round
25+: Bugs found & fixed
The project delivered five production workflows connecting WhatsApp, AI-powered report extraction, Supabase, and Stripe. Across five rounds of end-to-end testing, more than 25 bugs were identified and fixed, with over 30 test scenarios executed per round.
Technical Challenges & Solutions
During development and end-to-end testing, several integration and AI reliability issues required targeted solutions.
1. Stripe Subscription Data Handling
Challenge
The Stripe checkout event did not always contain all the subscription information required by the workflow.
Solution
Retrieved the complete subscription details directly through the Stripe API before continuing with subscription processing.
Outcome
Improved the reliability of subscription data handling.
2. Subscription Plan Mapping
Challenge
Mapping subscription plans based on payment amounts could lead to incorrect plan identification.
Solution
Used Stripe product IDs to identify plans instead of relying on monetary amounts.
Outcome
Made plan identification more consistent across subscription events.
3. AI Hallucination Control
Challenge
Claude AI could occasionally introduce materials or details that were not present in the worker’s input.
Solution
Refined the AI prompt with guardrails to discourage unsupported details and keep extraction grounded in the supplied information.
Outcome
Improved the consistency of structured report generation.
4. Supabase PATCH Response Handling
Challenge
Some Supabase PATCH operations returned empty responses, creating difficulties for downstream workflow nodes.
Solution
Explicitly referenced upstream node outputs where required instead of relying on the PATCH response to provide all subsequent data.
Outcome
Made downstream data handling more reliable.
5. End-to-End Integration Testing
Challenge
The system depended on multiple connected services, including WhatsApp, AI models, Supabase, and Stripe, making integration failures difficult to isolate.
Solution
Conducted five rounds of end-to-end testing, covering more than 30 scenarios per round, and fixed over 25 identified bugs.
Outcome
Improved integration reliability across the production workflows.
Key Takeaways & Future Development
Key Takeaways
Workflow automation: Built and integrated five production n8n workflows connecting WhatsApp, AI services, Supabase, and Stripe.
AI reliability: Improved structured report extraction through prompt engineering, validation, and guardrails against unsupported details.
Integration engineering: Resolved issues involving Stripe subscription events, plan mapping, and Supabase response handling.
End-to-end testing: Completed five testing rounds, identifying and fixing more than 25 bugs across the integrated system.
Cross-functional collaboration: Coordinated with the frontend engineer on database requirements and data contracts to connect backend workflows with the React dashboard.
Closing Summary
MeinBüromeister demonstrates how workflow automation, AI-powered information extraction, and integrated SaaS infrastructure can simplify construction reporting. The primary contribution was engineering the backend workflows and integrations that connect field communication with structured reports, subscription management, and the office dashboard.
Turning customer voice notes, photos and text messages on WhatsApp into instant, database-backed answers through an n8n workflow.
Section: n8n Automations, AI Agents for WhatsApp
Overview
This project is a WhatsApp business assistant for an online store. Customers write, speak or send a photo, and the workflow replies on WhatsApp with facts taken from the store’s Supabase product database, answering by voice when the customer used voice. It runs on n8n cloud with OpenAI models and replaces manual answering of repetitive product questions.
The business problem
Store owners answer the same questions all day: is this in stock, what does it cost, how long is delivery. Customers send these as voice notes, typed messages or screenshots of a product, so a simple keyword bot cannot read them. Slow replies lose sales, and a bot that guesses prices or stock damages trust.
The solution
An n8n workflow receives every WhatsApp message and routes it by type. Voice notes are transcribed, photos are described by a vision model, and text goes straight through. All three are normalized into one message and passed to an AI agent that must look up facts in Supabase before answering. The reply goes back as text, or as a voice note when the customer sent audio. Memory keyed on the customer’s phone number keeps the conversation connected.
Every message passes through six stages, from the customer’s WhatsApp message to the reply, in a single n8n workflow.
Step
Process
1. WhatsApp input
The customer sends a voice note, a text or a photo. The WhatsApp Trigger node receives it.
2. Routing
A Switch node checks the message type and sends it down the audio, text or image path.
3. Media handling
Voice notes and photos are downloaded through the WhatsApp media API. A voice note is transcribed and a photo is described by a vision model.
4. Normalizing
Edit Fields nodes turn each path into the same two fields: the message text and the customer’s phone number as session id.
5. AI agent
The agent looks up facts in the Supabase products table, thinks again, and writes a short reply. It remembers the conversation by phone number.
6. Reply
If the customer sent audio, the reply is converted to speech and sent as a voice note. Otherwise it is sent as text.
The workflow in n8n
Image: The top branch handles voice notes, the middle branch handles text, and the bottom branch handles photos. All three meet at the AI Agent, which has its model, memory, a Think tool and the Supabase Vector Store attached.
Supporting integrations
WhatsApp Business Cloud API: receives customer messages, downloads media and sends replies.
OpenAI: transcribes audio, describes images, runs the agent (GPT-4.1-mini) and creates the spoken reply.
Supabase: vector store over the products table, queried by the agent as a tool.
n8n Simple Memory: keeps recent messages per customer phone number.
Core Workflow Configuration
The workflow is built from a handful of node groups. Each one has a single job and passes the same two fields forward, so the agent never needs to know how the message arrived.
Node group
Configuration
WhatsApp Trigger
Listens for message updates from the WhatsApp Business Cloud API.
Switch
Three rules: audio (by mime type), text (by message type) and image (by mime type).
Download media + HTTP Request
Gets the media URL from WhatsApp, then downloads the file with the WhatsApp credential. Used for both audio and images.
Transcribe a recording
OpenAI audio transcription of the downloaded voice note.
Analyze image
OpenAI vision (GPT-4o-mini) on the downloaded photo, returned as a text description.
Edit Fields (three)
Set userMessage (the text, transcript or image description) and sessionId (the customer’s phone number).
AI Agent
GPT-4.1-mini with a system prompt: short WhatsApp-style replies under 80 words, one emoji at most, never guess, answer only from the database, hand complex issues to human support.
Simple Memory
Window memory keyed on the customer’s phone number.
Supabase Vector Store
Retrieve-as-tool on the products table, with OpenAI embeddings.
Think
A reasoning tool the agent can use before answering.
If
Checks whether the original message was audio.
Generate audio + Send voice reply
Turns the answer into speech and sends it back as an audio message.
Send message
Sends the answer as a WhatsApp text message.
Product Experience
These three mockups show how the assistant is meant to feel on the customer’s phone, one for each input type. They are illustrative designs, not screenshots of live conversations. The status messages (“Transcribing…”, “Searching our catalog…”) and the Shopify order lookup and replacement order shown in scenarios 1 and 3 are not in the current workflow and belong to a planned extension.
Scenario 1: voice input
Image: The customer sends a voice note. The workflow transcribes it, the agent finds the answer, and the reply comes back as a voice note because the customer used voice.
Scenario 2: text input
Image: A typed question goes straight to the agent, which checks the product data and answers in two or three short lines, with a follow-up question to move the sale forward.
Scenario 3: image input
Image: A photo is described by the vision model, and that description is handled as the customer’s message. In the current workflow the agent matches it against the product table. Order lookup and replacement orders are future work.
Results & Metrics
The workflow is built and cleaned up, and no live customer data has been measured yet. The figures below describe what was delivered. Response time, accuracy and conversion numbers should be added after a pilot with real conversations.
Metric
Result
Production workflows
1 main agent workflow
n8n nodes
21 after cleanup
Input types supported
3: voice note, text, photo
Reply formats
2: text and voice note
AI models used
4: transcription, vision, agent, speech
Knowledge source
Supabase products table, searched by the agent as a tool
Workflow defects fixed
2 (placeholder Code node, wrong message type)
Live response time and accuracy
Not measured yet
Technical Challenges & Solutions
Reviewing the exported workflow turned up problems that would have stopped it from working in production.
Voice reply could not be sent
Challenge
The voice path ended in a Code node that still held the placeholder YOUR_BASE64_STRING_HERE, and the send node used the document message type.
Solution
Removed the Code node, connected “Generate audio” directly to the send node, renamed it “Send voice reply”, and set its message type to audio with the customer’s number as recipient.
Outcome
The voice path is complete from the audio message to the voice reply.
Credentials missing after import
Challenge
After importing the workflow into a new n8n account, every WhatsApp, OpenAI and Supabase node showed a warning.
Solution
Reselect the credentials on each flagged node. For presentations, a demo copy with sample output pinned on the main-path nodes can be used.
Outcome
The nodes can be run green once credentials are set. A demo copy was prepared for the voice path.
AI answers must stay factual
Challenge
A sales assistant that invents prices or stock levels loses customer trust.
Solution
The system prompt requires the agent to retrieve facts from Supabase before answering, to ask when data is missing, and to hand complex issues to human support. Replies are capped at 80 words.
Outcome
Answers stay short and grounded in the product table.
Secrets inside workflow files
Challenge
A related Shopify workflow contains an access token written directly into its HTTP nodes.
Solution
Rotate the token and move it into an n8n credential before sharing or publishing that workflow.
Outcome
Open item, to be done by the store owner.
Key Takeaways & Future Development
Key takeaways
One agent for three input types: routing by message type and normalizing to the same two fields keeps the agent simple.
Grounded answers: forcing a database lookup before every reply is what keeps the assistant safe to put in front of customers.
Voice in, voice out: answering in the customer’s own format makes the assistant feel natural on WhatsApp.
Future development
Connect Shopify so the agent can check order status and create replacement orders, as shown in the mockups.
Add progress messages such as “Transcribing your voice message” while longer steps run.
Hand over to a human on WhatsApp, with the conversation passed to the support team.
Run a pilot with real customers and record response time, answer accuracy and sales conversion.
Move secrets such as the Shopify token into n8n credentials.
An end-to-end system for automated inbound lead scoring, enrichment, and real-time sales routing, powered by GPT-4.1 and n8n.
Section: Custom SaaS Platforms
Image: The lead form with a sample lead and the AI results card: score, HOT category, intent, budget, urgency, ICP match, summary and recommended action.
Most sales teams receive inbound leads from multiple sources (website contact forms, paid ad landing pages, partner referrals, and API integrations) and have no consistent, fast way to decide which ones deserve immediate attention.
The core problems the team was facing:
No consistent scoring methodology: qualification decisions depended on whoever happened to read the form first, leading to missed opportunities and wasted rep time
Hot leads were going cold: without instant routing, a prospect who said “ASAP, budget approved” could wait hours before a rep saw the submission
Company intelligence had to be looked up manually: reps spent time researching the company behind an email address before they could even decide whether to respond
No tiered escalation: there was no system to distinguish between a lead that needed a call in the next hour versus one that could go into a drip sequence
No unified lead record: repeat contacts from the same email were logged as separate entries, losing the interaction history
The goal was to build a fully automated intake-to-routing pipeline: AI scoring that runs in under two seconds, automatic company enrichment from the email domain, tiered alerts that reach the right person at the right time, and a central record of every lead with full analysis history.
What this system does
The system is composed of three interconnected layers: a lead intake API, a backend processing pipeline, and a real-time alerting engine, all orchestrated through n8n and a Node.js Express server.
Lead intake
Accepts inbound leads via a hosted landing page form, a direct REST API call, an embedded form webhook, or an n8n-triggered workflow
Validates required fields (name, email) and normalises all input before processing begins
Detects repeat submissions from the same email address: existing records are updated with the new interaction rather than duplicated
Supports a source field to track which channel each lead arrived from (website, paid ad, referral, n8n, etc.)
AI scoring engine
Each lead is analysed by GPT-4.1 across five dimensions: budget signals, urgency language, purchase intent, ICP (Ideal Customer Profile) match, and email quality
Returns a structured score from 0–100 and classifies the lead as HOT, WARM, or COLD
Produces a 12-field analysis object: score, category, intent, budget, urgency, ICP match, AI summary, recommended action, key signals, risk factors, estimated deal size, and sales rep assignment
Falls back to a rule-based keyword scoring engine if the OpenAI API is unavailable, guaranteeing zero-downtime operation
Enrichment layer
Extracts the company domain from the lead’s email address and enriches it with external company intelligence
With Clearbit: pulls company name, industry, employee count, estimated revenue, tech stack, LinkedIn URL, and headquarters location
Without Clearbit: performs basic domain analysis, infers company name, identifies TLD-based region, and confirms it is a business (not free) email
Free email providers (Gmail, Yahoo, Hotmail, etc.) are skipped for enrichment and flagged accordingly
Alerting and routing
Fires Slack alerts for every HOT lead: rich Block Kit messages, including all 12 analysis fields, AI summary, estimated deal size, and assigned sales team
Routes WARM leads to a nurture queue for email sequence follow-up
Archives COLD leads automatically with no sales action triggered
All notification steps run asynchronously, so they never delay the API response back to the form or caller
CRM integration
Pushes every processed lead to Airtable with 18 mapped fields, including all analysis outputs
Designed to be swapped for HubSpot or any other CRM with a single service file change
Skips gracefully if CRM credentials are not configured: the pipeline continues without interruption
Benefits
Hot leads reach a rep in seconds, not hours, the moment a high-intent submission arrives, a Slack alert lands in the right channel with everything the rep needs to act
Consistent, bias-free scoring: every lead is evaluated against the same GPT-4.1 criteria, removing the inconsistency of human triage
Company intelligence without manual research: reps open a Slack alert and already know the company’s industry, size, and tech stack
Zero-downtime resilience: if the AI API goes down, rule-based fallback scoring keeps the pipeline running
Unified lead history: repeat contacts are detected, and interactions are appended to the original record, preserving full context
Clean data from day one: lead sources are tracked, free email submissions are flagged, and all records share a consistent schema
Scalable without config changes: new lead sources plug in via the webhook endpoint; the pipeline handles volume automatically
How it works (simplified)
A lead arrives via the landing page form, a direct API call, an embedded form, or an n8n webhook, all routes converge on the same processing pipeline
The system checks for a repeat submission by looking up the email address in the lead store; if found, the new interaction is logged against the existing record
The lead is enriched: the email domain is used to pull company data from Clearbit, or a basic domain analysis runs as a fallback
GPT-4.1 analyses the lead: the full enriched record is submitted to the AI with a structured scoring prompt; a 12-field JSON response is returned in under two seconds
The lead is stored in the in-memory data layer (replaceable with PostgreSQL or Supabase) and a full analysis record is written
HOT lead → Slack alert is sent to the relevant sales channel, tagging the assigned rep team with the full AI summary and deal estimate
WARM lead → nurture queue: logged for drip email sequence follow-up
COLD lead → archived: stored for reference with no immediate sales action
The CRM is updated asynchronously: Airtable receives the full 18-field record without blocking the API response
The caller receives an instant response: the full analysis JSON is returned to the form or API caller within the same two-second window
System architecture (simplified)
Image: Architecture: four lead sources feed an Express backend with a five-step pipeline (validate, repeat detection, Clearbit enrichment, GPT-4.1 scoring, store), which routes to Slack alerts, an Airtable CRM and a nurture queue.
Ops-controlled settings (thresholds, routing rules, and CRM field mappings) are managed through environment configuration:
Setting
Where Configured
What It Controls
OPENAI_API_KEY
.env file
Enables AI scoring via GPT-4.1
SLACK_WEBHOOK_URL
.env file
Destination channel for HOT lead alerts
AIRTABLE_API_KEY + BASE_ID
.env file
CRM destination for all processed leads
CLEARBIT_API_KEY
.env file
Enables full company enrichment (optional)
Alert Toggle (per lead)
Google Sheets control layer
Enable or disable alerts per lead source
Score thresholds
Prompt config in aiService.js
Adjustable scoring bands per business context
Dashboard overview
Lead analysis results panel
The lead form renders a live results card immediately after submission, displaying the AI score, category, intent rating, budget signal, urgency level, ICP match, and a plain-English summary of why the lead scored the way it did, along with a specific recommended next action.
Renders in the browser within ~2 seconds of form submission
Slack alert panel
When a lead is classified as HOT, a Block Kit alert fires to the configured Slack channel. The message includes: lead name and company, email, phone, all five scoring dimensions, the AI-generated summary, recommended action, estimated deal size, and assigned sales team, formatted as a structured card with section dividers.
Delivered to the #sales-alerts channel within seconds of submission
Analytics dashboard
The /dashboard page provides a live operations view of all processed leads: total volume, HOT / WARM / COLD breakdown, average score, conversion rate, leads today, leads this week, top sources by volume, and a filterable lead feed. Data is drawn directly from the in-memory store and refreshes on page load.
Accessible at /dashboard: no login required in base configuration
Project evolution & key milestones
The system scope grew significantly from the initial lead scoring proof-of-concept. Key additions and refinements delivered across the project lifecycle:
Core scoring engine
Initial GPT-4 integration replaced with GPT-4.1 for faster, more consistent structured output
AI temperature set to 0.3 after testing: balances consistency with contextual sensitivity
Strict JSON output schema enforced via system prompt to eliminate parsing failures
Rule-based fallback engine added to ensure zero downtime when the OpenAI API is unavailable
Score validation and sanitisation layer added (score clamped 0–100; category constrained to enum)
Enrichment layer
Clearbit integration added as the primary enrichment source for business email domains
Domain-only fallback implemented: company name inference, TLD region mapping, business email detection
Free email provider list maintained to skip enrichment for Gmail, Yahoo, Hotmail, iCloud, ProtonMail, and similar
Alerting system
Slack alerts upgraded from plain text to full Block Kit format with eight labelled fields and section dividers
All notification steps moved to asynchronous execution to keep main API response time under two seconds
CRM push also made non-blocking: Airtable delays no longer affect the caller experience
Data and integration
n8n webhook route added (/api/webhook/n8n) to support visual workflow orchestration
Embedded form endpoint added (/api/webhook/form) for third-party form providers
Importable n8n workflow JSON file shipped with the project for instant setup
Airtable CRM integration added with 18 mapped fields; designed as a swappable service module
Memory layer and analytics
Repeat lead detection added: duplicate email submissions update the existing record rather than creating a new one
Interaction history log added to each lead record for full contact context
Analytics aggregation engine built into the storage service: computes category counts, average score, conversion rate, score distribution, top sources, and temporal metrics on demand
Dashboard feed endpoint added with configurable pagination and category/source filters
Security and production hardening
Helmet HTTP security headers added across all routes
Rate limiter set to 100 requests per 15 minutes per IP on all /api/* routes
Request body size capped at 1 MB to prevent oversized payload attacks
Explicit timeouts set on all external API calls (OpenAI: 30s · Clearbit: 5s · Airtable: 10s · Slack: 5s)
Global error handler middleware added to prevent stack traces leaking to API callers
Data flow architecture
How data moves through each stage and at what cadence, a key reference for ops teams integrating this system into existing stacks:
Stage
Source
Destination
Trigger
Intake
Form / API / n8n webhook
Express backend
On submission (real-time)
Enrichment
Clearbit API / domain analysis
Lead record (in memory)
Per lead, synchronous
AI Scoring
OpenAI GPT-4.1
Lead record (in memory)
Per lead, synchronous
CRM Push
In-memory lead record
Airtable (18 fields)
Per lead, async (non-blocking)
Slack Alert
In-memory lead record
Slack channel (HOT only)
Per lead, async (non-blocking)
Dashboard
In-memory lead store
Browser via /dashboard
On page load / manual refresh
Note
The current storage layer uses an in-memory Map for speed and simplicity. For production deployments requiring persistence across restarts or horizontal scaling, this is designed to be swapped for PostgreSQL, Supabase, or MongoDB, the storage service exposes a clean interface with no direct database calls in the route layer.
Lead scoring & classification
The AI scoring engine evaluates every lead across five weighted dimensions and assigns a 0–100 score. Classification thresholds are:
Category
Score Range
Routing Action
Criteria
HOT
80 – 100
Immediate Slack alert + rep assignment
Clear budget, urgency signal, decision-maker identified, strong ICP match
WARM
50 – 79
Added to nurture email sequence
Some buying signals, partial ICP match, needs further qualification
COLD
0 – 49
Archived, no immediate action
No clear intent, no budget signals, poor ICP fit or generic enquiry
The five scoring dimensions GPT-4.1 evaluates are:
Budget: explicit dollar amounts, investment language, company size inference
Automatically sorting a backlog of HubSpot companies into industry groups with Google Gemini, and flagging the ones that need a human.
Section: n8n Automations, AI Agents
Overview
This project is an automation that fills in the Industry Group field on HubSpot company records. An n8n workflow runs every hour, takes companies from a HubSpot list, skips the ones that already have an industry group, asks Google Gemini to pick one group for each, and writes the answer back to HubSpot together with a confidence score and a one-line reason. Companies it cannot classify with confidence are marked Needs R&D for a person to review instead of being forced into a wrong category.
The business problem
A CRM is only useful for segmentation and reporting when every company has an industry. Filling the field by hand for a long backlog of companies is slow, and different people choose different categories for the same kind of business. Letting an AI write straight into the CRM brings its own risks: an invented category, a low-confidence guess recorded as fact, or the same company processed over and over.
The solution
The workflow reads the allowed Industry Group options directly from HubSpot, so the AI can only choose values that exist. Each company is handled one at a time. Gemini returns a single group, a confidence score and a reason in JSON, and a code node checks that the answer matches a real HubSpot option and clears a confidence threshold before anything is written. Anything that fails that check is labelled Needs R&D. A dry-run switch lets the team test the whole flow without changing any record.
Project snapshot
Item
Detail
Platform
n8n
Trigger
Schedule, every hour
CRM
HubSpot (companies, a list of companies to process, the hs_industry_group property)
AI model
Google Gemini Flash, temperature 0.2, no web search
Batch size
Up to 100 companies per run, one at a time
Confidence threshold
0.6
Safety switch
dryRun setting, off by default
Workflow size
22 nodes
Status
Active
How the System Works
Each run follows the same six stages, from the schedule firing to a company updated in HubSpot.
Step
Process
1. Schedule and setup
The Schedule Trigger starts the run every hour. Two things happen in parallel: the workflow loads the allowed Industry Group options from HubSpot, and sets its configuration (companies per run, confidence threshold, dry-run flag and the HubSpot list id).
2. Collect the backlog
The workflow pages through the HubSpot list, 250 members at a time, until it has the configured maximum of 100 companies, then splits them into single items.
3. One company at a time
A loop takes each company and fetches its name, domain, website, additional domains and current industry group. Companies that already have an industry group are skipped.
4. Prepare and check
A code node cleans the domains. If a company has neither a domain nor a name, it is skipped because there is nothing to classify.
5. Gemini classification
Gemini receives the name and domain with the list of allowed groups and the classification rules, and returns JSON with the industry, a confidence score and a reason.
6. Validate and write
A code node matches the answer to a real HubSpot option and applies the confidence gate. Unless dry run is on, the result is written to HubSpot, followed by a Wait node before the next company.
The workflow in n8n
Image: The two chains on the left prepare the run: the top one loads the valid industries, and the bottom one pages through the HubSpot list. The loop in the middle processes one company at a time through the Gemini step.
Supporting integrations
HubSpot: the list of companies to process, the company records, the allowed Industry Group options and the update call.
Google Gemini: the classification model, with web search switched off so it answers from its own knowledge.
n8n workflow static data: holds the pages of list members while they are being collected.
Core Workflow Configuration
The workflow is built from a handful of node groups. Settings that a person may want to change are kept together in one Init Search Config node.
Node group
Configuration
Schedule Trigger
Runs every hour.
Get Industry Group Options / Extract Valid Industries
Reads the hs_industry_group property definition from HubSpot. Builds the list of allowed labels, leaving out hidden options and Needs R&D (which is added back in the prompt), and keeps the raw options for matching later. Retries up to 3 times, 5 seconds apart.
Init Search Config
Sets maxCompanies 100, confidenceThreshold 0.6, dryRun false and listId 638.
Get List Memberships / Accumulate List Members / Has More List Pages?
Pages through the HubSpot list 250 members at a time, stores them in workflow static data and stops at the company limit.
Collect List Members / Split Company IDs
Trims the collected members to the limit, clears the stored data and splits them into one item per company.
Loop Companies (1 at a time)
Processes one company per round. Its finished output goes to Backlog Run Complete, which records the completion time.
Get Company
Fetches name, domain, website, additional domains and current industry group from HubSpot. Retries up to 3 times.
IF Industry Group Missing
Continues only when the industry group is empty, so companies already classified are never touched again.
Clean Domain (code)
Strips protocol, www, paths and ports from the domain, website and additional domains, removes duplicates and builds a clean domain list.
IF Searchable
Continues only if the company has at least one domain or a name.
Gemini Classify Industry
Gemini Flash at temperature 0.2 with a detailed prompt: allowed groups, group definitions, classification rules and a JSON output format. Web search is off. Retries up to 5 times.
Match Industry Value (code)
Reads the JSON from the model, caps the confidence at 0.65 when there is no domain, and matches the chosen group to a real HubSpot option by label, value or a normalized form.
Prepare Company Update (code)
Applies the confidence gate and builds the HubSpot properties: the group (or Needs R&D), confidence, a reasoning text cleaned of stray characters and limited to 500 characters, a status and the check date.
IF Dry Run? / Dry Run - Skip Update
In dry run mode the update is skipped and the loop continues.
Update Company Industry Group
PATCH request to the HubSpot company record. Retries up to 3 times.
Wait1
Pauses before the next company to stay within HubSpot rate limits.
Classification Rules and Scenarios
What the model is told
Gemini must choose exactly one group from the list HubSpot provides. The prompt defines each group (for example Manufacturing, eCommerce, Retail, Wholesale Distribution, SaaS, Development shop, IT / MSP, Low Voltage, Consulting, Finance, 3PL, Transportation, Energy Rebates and Self Storage) and sets rules for the edge cases:
Businesses that sell physical products to consumers are never excluded. They go to Retail (walk-in stores) or eCommerce (online-first and direct-to-consumer brands).
Local consumer services, restaurants, medical and dental practices, schools, religious organizations and home services are marked Needs R&D with full confidence and an excluded flag.
A company that cannot be identified, or fits none of the groups (such as a law firm or nonprofit), is marked Needs R&D instead of being forced into a group.
Confidence is 0.80 to 1.0 when the company is clearly known, 0.40 to 0.65 for partial evidence or a name with no domain, and 0.0 when nothing can be verified.
The answer must be a single JSON object with industry, confidence, excluded and reasoning.
Scenarios
These scenarios show how the workflow treats the main kinds of company. They are illustrative, derived from the prompt and code, and are not recordings of real HubSpot records.
Scenario
What arrives
What the workflow does
Result in HubSpot
1. Clearly known business
A company with a domain whose business model the model recognizes, for example a software platform.
Gemini returns the matching group with confidence 0.80 or higher. The code matches it to a HubSpot option and it passes the 0.6 gate.
Industry group set, status updated, confidence and reason saved.
2. Consumer brand
A clothing or electronics brand selling to the public.
Rule 3 sends it to Retail or eCommerce, never to Needs R&D.
Retail or eCommerce group set.
3. Local consumer service
A pizzeria, dental practice or salon.
Excluded under rule 4 with confidence 1.0.
Group set to Needs R&D for a human to see.
4. Unknown company
A company the model cannot identify.
Returns Needs R&D with low confidence, so the gate fails.
Group set to Needs R&D, status low_confidence or unmatched.
5. Name only
A company with a name but no domain.
Confidence is capped at 0.65 in code, so the model cannot be fully sure.
Written only if it still clears 0.6, otherwise Needs R&D with status no_domain.
6. Already classified
A company that already has an industry group.
Stopped by IF Industry Group Missing, no model call.
Unchanged.
7. Dry run
Any company, with dryRun set to true.
Everything runs except the HubSpot update.
Nothing written.
Results & Metrics
The workflow is built and marked active. No run results were provided, so classification accuracy, the share of companies sent to Needs R&D and the time saved have not been measured.
Metric
Result
Production workflows
1
n8n nodes
22
Trigger
Schedule, every hour
Companies per run
Up to 100, processed one at a time
Industry groups
Read live from HubSpot, so the model cannot pick a value that does not exist
Confidence gate
0.6, with a 0.65 cap when a company has no domain
Fields written per company
Industry group, confidence, reasoning, status and check date
Safety features
Dry-run switch, skip of already classified companies, Needs R&D fallback, retries on every network and model call
Accuracy, volume, time saved
Not measured yet
Technical Challenges & Solutions
The model could invent a category
Challenge
A free-text answer such as “Software” or “Tech services” does not match any HubSpot option and would break the update or pollute the field.
Solution
The allowed groups are loaded from HubSpot on every run and given to the model to copy exactly. The answer is then matched to a real option by label, value or a normalized form that ignores case, punctuation and “&” versus “and”.
Outcome
Only values that exist in HubSpot can be written.
A weak guess recorded as fact
Challenge
A model will always give an answer, even when it knows nothing about the company.
Solution
The model must return a confidence score, name-only companies are capped at 0.65, and a code node only writes a group when the answer matches an option and reaches 0.6. Everything else becomes Needs R&D, and the confidence, reason, status and check date are saved on the record.
Outcome
Doubtful cases are visible to a person instead of hidden among correct ones.
Processing the same companies again
Challenge
An hourly schedule over the same list would classify the same companies on every run and waste model calls.
Solution
The workflow only continues when the industry group is empty, so each company is processed once.
Outcome
Each run moves on to the next unclassified companies.
Reading a long list from HubSpot
Challenge
The HubSpot list API returns 250 members per page, and the run must stop at a fixed number of companies.
Solution
A loop collects pages in workflow static data until the next page is missing or the limit is reached, then clears the data and splits the members into single items.
Outcome
Runs are bounded and predictable.
Testing without touching real data
Challenge
Changing the prompt or rules on live CRM records is risky.
Solution
A dryRun setting runs the whole flow, including the model call, but skips the HubSpot update.
Outcome
The prompt can be tuned and checked before records are changed.
Open items found in the export
Challenge
Three details in the workflow need checking. The Wait node after each update has an amount of 10 but no unit stored, and n8n’s default unit for that node is hours. The prompt refers to a Seamless Data field that no earlier node fills, so it is always “N/A”. The collected list members sit in static data, so a run that fails halfway through paging could leave old members behind for the next run.
Solution
Open the Wait node and set the unit to seconds. Either feed the Seamless description into the prompt or remove the line. Clear the stored list at the start of each run.
Outcome
Not done yet. These are the first improvements to make.
Key Takeaways & Future Development
Key takeaways
Let the CRM define the answers: loading the allowed groups from HubSpot keeps the model inside the structure the team already uses.
Check the model’s output in code: a confidence gate and a strict match to real options decide what is written, not the model alone.
Send doubt to a person: Needs R&D with a stored reason turns uncertain cases into a review list.
Make it safe to test: the dry-run switch, retries and the skip of classified companies make the workflow safe to leave running.
Future development
Set the Wait node unit to seconds and check that the Gemini model id is available in your account.
Fill the Seamless Data line in the prompt or remove it.
Clear the stored list members at the start of every run.
Create a HubSpot view of companies marked Needs R&D, sorted by confidence, so reviewers can work through them.
Send a short summary after each run (companies processed, written, flagged) using the Backlog Run Complete step.
Run a measured pilot, compare a sample of results with a person’s choices, and use it to complete the results section.
How Harrington & Cole LLP replaced four disconnected tools with one Airtable workspace, cutting matter-intake time by 68% and automating 1,200+ status touchpoints a month.
Harrington & Cole LLP is a 60-person law firm headquartered in Halifax, Nova Scotia, with three practice groups and a docket of roughly 230 active matters at any given time. By early 2025 the firm was running case intake, conflict checks, scheduling and time capture across four disconnected systems: a legacy practice-management tool, shared Excel files on a network drive, Outlook calendars, and a paper intake form. Status updates lived in attorneys’ heads and email threads.
Over an 11-week engagement we replaced this patchwork with a single Airtable workspace, purpose-built tables, role-specific Interfaces for attorneys and paralegals, and an automation layer that handles the firm’s repetitive coordination work. The implementation was delivered without disruption to billable work and went live with all 60 users on the same day.
Outcomes after 90 days in production
68%: Faster matter intake
1,284: Automated touchpoints / mo.
0: Missed SOL deadlines
$41K: Recovered WIP in Q1
At a glance
Before: 4 systems, ~6 hrs to open a new matter, manual conflict checks, scheduling done by email.
After: 1 Airtable workspace, ~2 hrs to open a matter end-to-end, conflict-check workflow runs in < 60 seconds, hearing prep tasks auto-spawn 14 days out.
Background
The client and the problem
About the firm
Harrington & Cole LLP serves regional commercial clients across Atlantic Canada. Three practice groups (litigation, corporate / transactional, and employment) share a managing partner, a central paralegal pool, and a single billing department. The firm had grown roughly 40% in headcount over five years; its tooling had not kept up.
The pain points that triggered the project
Matter intake took up to six hours. A new lead required duplicate data entry across four systems, with manual conflict checks against an Excel register that one paralegal owned.
Status was invisible. Partners had no reliable view of which matters were stuck in discovery, which were close to trial, or which had open balances over 60 days.
Deadline slips were happening. Two near-misses on statute-of-limitations dates in 2024 prompted the managing partner to require automated alerting as a non-negotiable.
Time capture was lossy. Attorneys logged time at week-end from memory; the firm estimated 6–9% of billable hours were being lost.
Reporting was a fire drill. The monthly management report took the office manager roughly two days to assemble from exports.
Why Airtable
The firm evaluated three traditional practice-management products and Airtable. The decision came down to three factors: (1) the firm wanted a system its own staff could change without a vendor ticket, (2) the data model needed to fit the firm’s terminology rather than force the firm into a vendor’s, and (3) the integration story with Slack, Outlook and DocuSign needed to be straightforward. Airtable’s linked-record model, Interface Designer, and native automation framework made it the right fit.
Approach
How the implementation was run
We delivered the implementation in four phases over eleven weeks. A core working group made up of the managing partner, two senior associates (one per practice area), the office manager, and a paralegal lead met twice a week to validate the data model, review prototypes, and sign off on go-live readiness.
Phase
Weeks
What we did
Output
1. Discovery
1–2
Shadowed intake, conflict-check and billing workflows. Mapped 14 existing data sources. Interviewed 11 attorneys and staff.
Process map, data dictionary, ranked pain-point list.
2. Data model & schema
3–4
Designed 10-table relational schema. Built linked records for Cases ↔ Clients ↔ Hearings ↔ Documents ↔ Tasks ↔ Time entries.
Live Airtable base with sample data; ER diagram.
3. Interfaces & automations
5–8
Built the Attorney Dashboard, the Paralegal Workbench and the Partner Reporting interfaces. Designed and tested 8 automations.
3 production interfaces; automation library.
4. Migration, training, go-live
9–11
Migrated 1,847 historical matters, trained all 60 users in three cohorts, ran a 5-day parallel-run before cutover.
Single-day cutover with zero data loss.
Guiding principles
Match the firm’s vocabulary. Field names mirror how attorneys actually speak (e.g. matter, not project; SOL date, not deadline).
One source of truth. Every piece of data lives in exactly one table; everywhere else uses a linked record, lookup or rollup.
Make the right thing the easy thing. Intake, conflict checks, and time capture were redesigned so the compliant workflow is the fastest workflow.
Internal ownership. The office manager and one senior paralegal were trained as base administrators; they own day-to-day changes.
What Was Built
The Cases table: the heart of the workspace
Every matter the firm works on is a record in the Cases table. From here, attorneys can see the entire docket grouped by practice area, filtered to their own matters, or sliced by stage. The grid below shows the production view used by senior associates each morning to triage their day.
Image: Figure 1: The Cases grid view, grouped by practice area. Coloured stage chips give partners an at-a-glance read on where every matter sits. The footer rolls up open balances and average days-open across the visible records.
Highlights of this view
Grouping by practice area mirrors how the managing partner thinks about workload distribution.
Stage is a single-select with a controlled vocabulary (Intake → Pleadings → Discovery → Negotiation → Trial Prep → Closed). It drives both the kanban view and three automations.
Lead Attorney links to the Staff table, so renaming or reassigning happens in one place.
Open Balance at the bottom is a rollup from the Time entries table, no manual reconciliation needed.
Two more views the firm uses every day
Kanban by stage is how partners review pipeline in their Monday morning meeting. Dragging a card moves the matter through the lifecycle and triggers the corresponding automation chain.
Image: Figure 2: Kanban view of the Cases table, grouped by stage. Card colour and the avatar in the corner make ownership obvious even on a wall display.
The expanded matter record
Clicking any row opens a full-detail view of the matter. This is the single screen attorneys live in when they’re working a case. It consolidates parties, deadlines, team, financials and notes. WIP and Open Balance are rollups from the linked Time entries table; the Statute of Limitations warning is a formula that turns red automatically inside 90 days.
Image: Figure 3: The expanded record view for matter CASE-2024-0142. Rollups, formulas and linked records mean every number on this screen is computed live from the underlying tables: nothing is manually maintained.
The Data Model
Ten tables, one source of truth
The base is built around Cases as the central entity. Everything else (clients, hearings, documents, tasks, time, communications) links to a case. This single design decision is what makes the rollups, formulas and automations possible.
Image: Figure 4: The 10-table schema. Lines indicate linked-record relationships. Cases is the hub; Documents, Tasks, Time entries and Communications all link to a case.
Field-level decisions worth calling out
Stage is a single-select with synced colour. Changes here trigger 3 different automations.
SOL date is paired with a formula days_until_sol; the alert automation reads the formula field, so all date logic lives in one place.
Conflict_clear on Clients is a checkbox controlled by the conflict-check automation, an intake matter is blocked from advancing until this is true.
Time entries rolls up into Cases as WIP and Open Balance, so billing reports build themselves.
Communications is populated by the Gmail and Outlook integrations, every email about a matter is logged automatically.
Interfaces
Three role-based interfaces, one underlying base
Different people in the firm need different things from the same data. We built three Interfaces on top of the base, each tailored to a role. All three read from and write to the same tables. There is no duplication.
The Attorney Dashboard
This is the screen attorneys open when they sit down at their desk. It surfaces the four KPIs that matter to them, the next 30 days of hearings, and their personal task list, all filtered to their own user automatically.
Image: Figure 5: The Attorney Dashboard interface, scoped to the logged-in user. KPI cards on top; upcoming hearings and personal tasks below. Click-through on any matter title opens the full case record in a side panel.
Two other interfaces
Paralegal Workbench: task-centric view. Paralegals can claim open tasks, log time directly against a matter, and upload signed documents which auto-update the matter’s stage.
Partner Reporting: read-only firm-wide view with charts showing matters by stage, WIP trend, top 10 oldest open balances, and attorney utilisation. Replaces what used to be a 2-day monthly reporting exercise.
Automations
Automating the repetitive coordination work
Eight automations remove roughly 1,200 manual touchpoints from the firm’s month. None of them replace an attorney’s judgment: they remove the surrounding paperwork.
Image: Figure 6: The Automations panel. Eight automations, six currently enabled, with run counts visible per automation. The detail pane on the right shows the trigger and three actions of the hearing-reminder workflow.
The automation catalogue
Each automation is owned by a named person on the working group, documented in a Notion runbook, and reviewed quarterly.
#
Automation
Trigger
Actions
Replaces
1
New case → Conflict check workflow
Record created in Cases with stage = Intake
Searches Clients table for matches against parties, opposing counsel and judges. Posts result to Slack and sets conflict_clear if no match.
Manual lookup in Excel register
2
Hearing date approaching (14 d)
days_until formula on Hearings = 14 and status = Scheduled
Slack DM to lead attorney + creates 4 prep tasks (brief, exhibits, witness prep, filings).
Calendar reminders + paralegal phone calls
3
Statute of limitations alert (90/30/7 days)
Cases.days_until_sol formula crosses each threshold
Email to lead attorney; at 30d also CCs managing partner; at 7d escalates to a Slack channel.
Slack DM to managing partner with link to the entry.
End-of-month review (often too late)
6
Client onboarding sequence
Clients.conflict_clear changes to true
Sends client engagement letter via DocuSign, creates Drive folder with templates, books an intake call.
Three separate manual checklists
7
Weekly WIP digest
Schedule: every Monday 7:00 AM
Builds per-attorney summary of WIP, billed and aged AR; emails each lead attorney their digest.
Office manager spending Friday building reports
8
Stale matter (no activity 30 d)
Schedule: nightly scan
Sets a flag field; visible on the Partner Reporting interface for follow-up.
Nothing: these matters used to disappear
Worked example: automation #2 in detail
Trigger: a record in Hearings where the days_until formula evaluates to exactly 14 and status is Scheduled.
Action 1 (Find records): looks up the parent Case via the linked-record field to retrieve the lead attorney and client.
Action 2 (Send Slack): DMs the lead attorney with a deep link back to the case record and a one-line summary of the hearing.
Action 3 (Create tasks): creates four pre-templated prep tasks in the Tasks table, all linked to the same matter, with sensible default due dates working back from the hearing.
Replaced: three different paralegals each maintaining their own version of a hearing-prep checklist, and the senior associate manually pinging attorneys.
Integrations
How the workspace connects to the rest of the stack
Airtable doesn’t replace email, calendars, document storage or e-signature, and shouldn’t. It coordinates them.
System
Direction
What flows
Mechanism
Outlook / Microsoft 365
Two-way
Hearings sync to attorney calendars; calendar invites for new hearings auto-create Hearing records.
Microsoft Graph + Airtable sync
Gmail (firm address)
One-way (in)
Email referencing a matter ID is logged to the Communications table with a link back to the thread.
Native Airtable Gmail integration
DocuSign
Two-way
Engagement letters dispatched from Airtable; signed status triggers automation #4.
Webhooks via Airtable Automations
Slack
One-way (out)
Hearing reminders, SOL alerts, time-entry alerts, weekly WIP digests.
Native Slack action in Airtable Automations
Google Drive
One-way (out)
On client onboarding, a structured matter folder is created with the firm’s standard subfolder template.
Drive API call from Airtable script action
Notion
Reference only
Runbooks for each automation live in Notion; each Automation record has a URL field linking to its runbook.
Manual link
Permissions & data handling
Workspace plan: Airtable Business with SAML SSO via the firm’s identity provider. Two-factor authentication enforced for all 60 users.
Field-level permissions: rate cards, WIP and AR fields are read-only to associates; visible only to partners on the Partner Reporting interface.
Privileged matters: a checkbox on Cases hides a matter from all users not on its team via a row-level filter applied to every view.
Audit: Airtable’s revision history is retained, and a nightly snapshot is exported to the firm’s encrypted backup bucket.
Results
Measurable change after 90 days in production
Metric
Before
After
Change
Matter intake (lead → opened)
≈ 6 hours
≈ 1 hr 55 min
−68%
Conflict check turnaround
Up to 48 hr
< 60 sec (automated)
−99%
Missed SOL deadlines (rolling 12 mo.)
2 near-misses
0
−100%
Monthly management report build time
≈ 14 hours
≈ 25 min (live dashboard)
−97%
Time-entry capture latency
Avg. 4.2 days
Avg. 0.6 days
−86%
WIP recovered Q1 (vs. prior quarter)
n/a
$41,200
+ revenue
Automated touchpoints / month
0
1,284 (across 6 active flows)
n/a
Active users (firm-wide)
n/a
60 / 60
100% adoption
In the words of the firm
The thing that surprised me wasn’t the dashboards: it was the fact that we don’t talk about case status in hallways anymore. Everyone is looking at the same picture, and the system tells us when something needs attention before it becomes a fire. We have not had a near-miss on a deadline since the day we went live.
What we’d do again, and what we’d change
Worked well: embedding the working group from week one. Every design decision had a real attorney’s name attached to it, which made go-live painless.
Worked well: shipping the Attorney Dashboard before the Partner Reporting interface. Adoption is driven by the people doing the work, not the people watching the work.
Would change: we waited until phase 3 to wire up the Outlook two-way sync. In hindsight, that should have been in phase 2, calendars are how attorneys actually work.
Would change: add a fifth interface for the firm’s receptionist. Inbound caller intake is still slightly clunky.
Turning every email sent to a shared support inbox into a correctly routed, duplicate-free ClickUp ticket through one n8n workflow.
Section: n8n Automations, ClickUp Setups
Overview
This project is a support-intake automation for RefureTech. Customers email the shared support address, and the n8n workflow reads each message, works out which client it belongs to from the sender’s email domain, and files it in ClickUp. It becomes a new ticket in that client’s support list, a ticket in a triage list when the client is unknown, or a comment when a ticket for the conversation already exists. Attachments and earlier messages in the thread travel with it.
The business problem
Support requests arrive as ordinary email. Copying them into a ticket system by hand is slow and easy to get wrong: the wrong client, a missed reply, an attachment left behind in the inbox. The work grows with every new client. Automating it is not simple either, because ClickUp has its own Email ClickApp that sends a confirmation to the customer and files later replies as comments. A naive automation creates duplicate tickets or, worse, turns its own confirmation emails into new tickets in an endless loop.
The solution
A single n8n workflow polls the support inbox every minute. It looks up the client list stored in ClickUp, matches the sender by domain, checks four different ways whether the conversation already has a ticket or is already managed by ClickUp, and only then creates a ticket or comment. It uses plain, explainable rules in code nodes rather than an AI model, so every decision can be traced to a header, a subject line or a ClickUp field. Wherever a step could fail, the workflow prefers a duplicate ticket over a lost customer email.
Project snapshot
Image: Project snapshot.
How the System Works
Every email passes through six stages, from arrival in the inbox to a ticket in ClickUp, inside one workflow.
Step
Process
1. Email input
The Gmail Trigger polls the INBOX label every minute. The full message is fetched and its HTML body is converted to Markdown so it reads cleanly inside a ticket.
2. Client matching
The workflow reads the client list from ClickUp, where each client has a Domain, a folder id and a support list id. A code node picks the customer contact from the To, Cc and From addresses and matches its domain (or a parent domain) to a client. Free-mail and internal domains are never mapped.
3. Duplicate checks
Three lookups run: a ClickUp search by Gmail thread id, a ClickUp search by the thread ClickUp’s own confirmation email started, and a fetch of the full Gmail thread history.
4. Decision
Route Decision labels the email new, default, comment or skip. Two guard nodes can still turn a write into a skip: one if ClickUp’s ticket id is at the end of the subject, one if the mail headers show a machine-generated reply.
5. Ticket action
A Switch creates a ticket in the client’s list, creates a ticket in the triage list, or adds a comment to the existing ticket. The description holds the new message plus earlier messages in the conversation.
6. Attachments, label, sync
Attachments are downloaded and uploaded to the ticket, and the Gmail message is labelled as processed. For new tickets the workflow waits two minutes, finds ClickUp’s confirmation email and stores its thread id on the ticket so later replies are recognised.
The workflow in n8n
Image: The chain on the left reads the email, matches the client and checks for duplicates. The Switch in the middle sends each email to one of three ticket actions. Each action ends in its own attachment branch and a Gmail label step, and new tickets also pass through the wait and confirmation sync.
Supporting integrations
Gmail: trigger, message fetch with attachments, thread history, and labelling processed messages.
ClickUp: client routing data, ticket and comment creation, attachment upload, and custom fields that store the Gmail thread id and ClickUp’s email thread id.
Error workflow: a separate n8n workflow is attached in the settings to handle failures of this one.
Core Workflow Configuration
The workflow is built from a handful of node groups. Each has a single job, and the routing decision is carried forward as one item holding the same fields (contact, domain, folder, list, thread id, reason, action), so the ticket nodes never need to know how the decision was reached.
Node group
Configuration
Gmail Trigger
Polls every minute, restricted to the INBOX label on purpose. ClickUp sends its confirmation as the support address, which leaves a copy in Sent. Polling Sent would turn that confirmation into a ticket and trigger another confirmation, forever.
Get HTML + Markdown
Fetches the full message and converts the HTML body to Markdown. Retries up to 3 times, 2 seconds apart.
Get Support ID
ClickUp node that lists the client tasks. Each carries the custom fields Domain, folder_id and support_list_id.
Find ID from Domain (code)
Builds a domain-to-client map, ignores free-mail and internal domains, records domain collisions, picks the customer contact (mapped client first, then any external address, then the sender), validates every address, fills up to 20 Cc fields and applies the one hard skip: the self-addressed ClickUp acknowledgment.
Find Existing Ticket / Find ClickUp Email Thread
Two ClickUp API searches by custom field: the Gmail thread id, and the thread id of ClickUp’s own confirmation. If either call fails the workflow continues with no result, so a ticket is still created.
Get Thread History
Gmail API call for every message in the conversation. Failure is non-fatal: the ticket is created with the newest email only.
Route Decision (code)
Decides clickup_synced, comment, new or default, and assembles the ticket description with the earlier messages, capped at 60,000 characters.
ClickUp Already Owns This? (code)
Skips when the subject ends with a ClickUp ticket id such as #RTS-1234, or the confirmation wording is found. Anchored to the end of the subject so a customer’s own mid-subject reference such as #PO-88231 still gets a ticket.
Machine Auto-Reply? (code)
Skips out-of-office and bounce mail by reading headers (Auto-Submitted, X-Auto-Response-Suppress, Precedence, empty Return-Path), never the subject wording.
Switch
Six rules: new, default, comment, loop guard (skip), ClickUp synced (skip), auto-reply (skip). The fallback output goes to the triage list so an unexpected value cannot drop an email.
Create a task / Create Default Task
ClickUp nodes that create the ticket with the Markdown description, customer contact, recipient, up to 20 Cc contacts and the Gmail thread id as custom fields. Tickets opened mid-chain are titled with an [Ongoing thread] prefix.
Add Comment to Existing Task
Posts the new email as a comment on the tracked ticket without notifying everyone.
Attachment branches (3 sets)
Re-fetch the message with attachments, split them out, keep only files with a real file extension, upload them to the ticket and add the Gmail label. Emails without attachments still reach the label step.
Wait + confirmation sync
Waits 2 minutes, re-reads the task for its custom id, searches Gmail for ClickUp’s confirmation and saves its thread id into the ticket so future replies are recognised.
Product Experience and Routing Scenarios
Every email the workflow has handled is marked with a Ticketed label in Gmail, so the team can see at a glance which messages already have a ticket or comment in ClickUp. Replies on the same conversation carry the label too.
Routing scenarios
These scenarios show how the workflow treats the main kinds of email. They are illustrative, derived from the workflow logic, and are not recordings of real customer emails.
Scenario
What arrives
What the workflow does
Result
1. Mapped client, new request
A first email from someone at a client whose domain is in the ClickUp client list.
Matches the domain, finds no existing ticket, routes to the client’s folder and support list, uploads attachments, labels the email, then syncs ClickUp’s confirmation thread id after 2 minutes.
New ticket in the client’s support list.
2. Unknown domain
An email from a domain that is not mapped, or with no usable contact address.
Falls to the default branch. The ticket is still created, in the default triage list, with the sender as contact.
New ticket in the triage list for a person to assign.
3. Reply on a tracked conversation
A follow-up where a ticket already exists for the Gmail thread but ClickUp does not own the thread.
Finds the ticket by the Gmail thread id custom field and posts the email as a comment, then handles any attachments.
Comment and files added to the existing ticket.
4a. ClickUp-owned reply
A customer reply whose subject ends with a ClickUp ticket id.
Stops without writing. ClickUp’s Email ClickApp is already filing replies as comments, so acting would duplicate the ticket.
Skipped, no duplicate.
4b. Out-of-office or bounce
A vacation responder or delivery failure notice.
Detected from mail headers and skipped. A colleague’s real reply on the same thread is not skipped, because headers are checked instead of subject words.
Skipped, real replies kept.
4c. Our own confirmation
The ClickUp acknowledgment, sent from the support address back to the support address.
Hard skip by the loop guard.
Skipped, loop prevented.
Results & Metrics
The workflow is live and has run on the real support inbox. Business figures such as hours saved, tickets per week and routing accuracy have not been measured yet.
Metric
Result
Production workflows
1 main workflow, plus an error workflow attached in settings
n8n nodes
38
Trigger
Gmail polling every minute, INBOX only
Routing outcomes
6: new, default, comment, and three skip outcomes
Duplicate guards
4 layers: Gmail thread id, ClickUp email thread id, ticket id in subject, confirmation wording
Failure handling
Retries up to 3 times, 2 seconds apart, on every network node. Lookups fail open, so an email becomes a ticket rather than being lost.
9 runs took about 2 minutes (the path with the built-in 2-minute wait for ClickUp’s confirmation). 2 runs took about 4 seconds (paths without that wait).
Hours saved, accuracy, duplicate rate
Not measured yet
The execution count reflects only the executions n8n still retains and is not a full volume figure. The link between run time and path is inferred from the workflow design.
Technical Challenges & Solutions
Most of the engineering effort went into edge cases around ClickUp’s own email feature and around real-world email, where a simple “new email creates ticket” flow breaks quickly.
The workflow could answer itself forever
Challenge
ClickUp sends its confirmation email from the support address, so a copy lands in Sent. If the workflow read Sent, that confirmation would become a ticket, which triggers another confirmation, and so on.
Solution
The trigger watches INBOX only, and a loop guard in code skips any email sent from the support address with the support address in To or Cc. It is the only unconditional skip.
Outcome
The loop is closed twice, at the trigger and in the logic.
Duplicate tickets next to ClickUp’s Email ClickApp
Challenge
Once a ticket exists, ClickUp already files replies as comments and sends its own acknowledgment. Creating another ticket from the same reply duplicates work and makes ClickUp send the customer a second acknowledgment.
Solution
Four independent checks decide whether ClickUp owns the conversation: a stored ClickUp email thread id, the ticket id at the end of the subject, the confirmation wording in the thread, and the Gmail thread id on an existing ticket. The subject check is the most dependable, because older tickets lack the stored thread id and the confirmation wording can change.
Outcome
Replies on ClickUp-managed conversations are skipped and n8n stays out of the way.
Out-of-office mail versus a colleague covering for someone
Challenge
An auto-reply sets the subject to “Out of Office Re: …”. A colleague who replies on the same thread keeps that subject, so matching subject words would silently drop a genuine customer email.
Solution
The check reads mail headers that no human mail client sets (Auto-Submitted, X-Auto-Response-Suppress, Precedence, empty Return-Path). If the headers cannot be matched confidently to the right message, nothing is skipped.
Outcome
Machine mail is filtered out, and real replies with the same subject still become tickets.
A duplicate is acceptable, a lost email is not
Challenge
Lookups against ClickUp and Gmail can fail, and an email that stops the workflow is a customer who never gets answered.
Solution
The ticket-search and thread-history calls retry three times and then continue with no result. Missing results default to creating a ticket, the Switch fallback sends unknown outcomes to the triage list, and the split-out steps continue on error so every email still reaches the labelling step.
Outcome
Failures become an extra ticket or less context, never a dropped message.
Tickets opened in the middle of a conversation
Challenge
When the first email the workflow sees is already a reply, a ticket with only the latest message has no background.
Solution
The full Gmail thread is fetched, earlier messages are sorted by date and appended to the ticket description (with sender, recipient, date and subject), capped at 60,000 characters, and the title gets an [Ongoing thread] prefix.
Outcome
A person opening the ticket sees the whole conversation.
Malformed addresses breaking ticket creation
Challenge
ClickUp rejects the whole task when an email-typed field receives something that is not an address, such as a group name or undisclosed-recipients. Messy Cc lines and display names are common.
Solution
Header values are normalised, every address is validated, the support address is never mapped into contact fields, and Cc contacts are capped at 20 fields with the overflow count recorded.
Outcome
Odd headers no longer cause ticket creation to fail.
Secrets inside the workflow (open item)
Challenge
The ClickUp API token is written directly into the Authorization header of 8 HTTP Request nodes instead of an n8n credential, so it is visible to anyone who can open or export the workflow.
Solution
Create a ClickUp credential in n8n, switch those nodes to it, and rotate the token.
Outcome
Not done yet. The token is deliberately not reproduced in this document.
Key Takeaways & Future Development
Key takeaways
Design for the tool next door: the hardest part was coexisting with ClickUp’s own email automation, not creating tickets. Layered duplicate checks solved it.
Headers over words: deciding on machine-readable signals, such as mail headers and a ticket id anchored to the end of the subject, keeps genuine emails from being filtered out.
Fail open: choosing a duplicate over a lost email at every failure point makes the automation safe to leave running on a customer-facing inbox.
Configuration in ClickUp, not in code: adding a client means filling in three fields on a ClickUp task, with no change to the workflow.
Future development
Move the ClickUp token into an n8n credential and rotate it.
Log every skipped email (loop guard, ClickUp-owned, auto-reply) to a sheet or channel so skips can be audited.
Surface the domain collisions the code already detects, for example with an alert, so two clients cannot silently share a domain.
Replace the fixed 2-minute wait with a short retry loop that looks for ClickUp’s confirmation email.
Merge the three near-identical attachment branches into one shared sub-workflow.
Run a measured pilot and record tickets per week, time saved, routing accuracy and duplicate rate to complete the results section.