n8n tutorial - Lesson 08: Automated Email Digest to Telegram with n8n

n8n tutorial - Lesson 08: Automated Email Digest to Telegram with n8n

Hi everyone, in this post we'll build a Daily Email Digest to Telegram workflow using n8n — one of the most practical n8n telegram notification setups you can run fully automated. This is Session 8 of our n8n Workflow Automation Tutorial series, and by the end you'll have a live pipeline that summarizes your important emails every day at 6 PM and sends them straight to your phone.

How to do:

Step 1 — Create a Telegram Bot with BotFather

Before building anything in n8n, you need a Telegram bot token and your personal chat ID.
  1. Open Telegram and search for @BotFather, then send the command /newbot.
  2. Follow the prompts to name your bot and choose a username ending in bot (e.g., MyDigestBot). BotFather will reply with a bot token — copy and save it securely.
  3. Send any message to your new bot (e.g., "hello") so it has an active chat session to respond to.
  4. Retrieve your chat ID by calling the Telegram API in your browser:
    • Visit https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates
    • Find the chat.id field in the JSON response — this is the number you'll need later.

Tip — Save both the bot token and chat ID somewhere safe before moving to n8n. You cannot retrieve the token again from BotFather without revoking the old one.

Step 2 — Create the Telegram Credential in n8n

With your token ready, add the Telegram credential so n8n can send messages on your bot's behalf.
  1. In n8n, go to Credentials → New Credential and search for Telegram API.
  2. Paste your bot token into the Access Token field.
  3. Name the credential something descriptive like Telegram (Personal), then click Save.

Step 3 — Create the Workflow and Add a Schedule Trigger

The workflow is named T2-B6-Daily-Digest and starts with a time-based trigger set to fire every day at 6 PM.
  1. Create a new workflow in n8n and name it T2-B6-Daily-Digest.
  2. Add a Schedule Trigger node as the first node.
  3. Configure the trigger:
    • Set Trigger Interval to Days mode (not Minutes mode).
    • Set Hour to 18 and Minute to 0.
    • Set Timezone to Asia/Ho_Chi_Minh (or your local timezone).

Note — The Schedule Trigger has 6+ modes including Minutes, Hours, Days, Weeks, Months, and Custom (Cron Expression). For a daily digest, Days mode is the cleanest option — use Cron mode only if you need complex schedules like "every weekday at 6 PM."

Step 4 — Fetch Important Emails with Gmail Get Many

This node pulls emails from your labeled inbox using a Gmail search query scoped to the last 24 hours.
  1. Add a Gmail node and set the operation to Get Many.
  2. Set the Search Query field to label:n8n/Quan-trọng newer_than:1d — replace Quan-trọng with whatever label name your email classifier applies to important emails.
  3. Set Simplify to OFF — this is critical.
  4. Set Limit to 10.

Note — Simplify = ON sounds helpful but in practice the simplified output does not include headers.from or headers.subject. The Simplify=ON shape only exposes fields like id, threadId, snippet, payload.mimeType, sizeEstimate, historyId, internalDate, and labels. If you need sender name and subject line — and you do for a digest — you must use Simplify = OFF. This was a confirmed bug in earlier session notes and has been corrected.

Step 5 — Merge Emails into a Single Batch with a Code Node

Because the AI node needs all emails in one prompt, a Code node combines every email item into a single text block before passing it forward.
  1. Add a Code node after the Gmail node.
  2. Set Run Once for All Items (not once per item) — this is what allows the node to see and merge all emails together.
  3. Inside the code, build three variables:
    • count — total number of emails retrieved.
    • today — today's date formatted as a readable string.
    • emails_text — a concatenated string of all emails, each truncated to 250 characters.
  4. For the email body, use a fallback: prefer j.text if available, otherwise fall back to j.snippet. After selecting the value, normalize whitespace and cut to 250 chars.
  5. Return a single item containing emails_text, count, and today so the next node receives one combined object.

Tip — The 250-character truncation keeps the AI prompt compact and avoids hitting token limits, especially when you have 10 emails. The fallback from j.text to j.snippet ensures the node doesn't crash on emails where full body parsing fails.

Step 6 — Summarize with an AI Node (Claude Haiku)

A Basic LLM Chain node takes the merged email text and produces a clean, formatted Telegram-ready summary.
  1. Add a Basic LLM Chain node and connect it to the Code node.
  2. Select your AI model — this workflow uses Claude Haiku 4.5.
  3. Set model parameters:
    • Temperature: 0.3 (low, for consistent factual summaries)
    • Max Tokens: 1500
  4. Write a system/user prompt that includes these explicit rules for Telegram Markdown:
    • Bold text must use *bold* (single asterisk) — NOT **bold**. Telegram uses legacy Markdown, not standard Markdown.
    • Avoid italic (_text_) where possible — it renders inconsistently in Telegram legacy mode.
    • Use placeholder square brackets [ ] as the prompt instructs for structured output sections.

Note — This Markdown difference is easy to miss: AI models default to writing **bold** (two asterisks, standard Markdown) but Telegram's legacy parse mode only renders *bold* (one asterisk). If you skip this rule in the prompt, your digest will arrive with raw asterisks showing as plain text instead of bold formatting.

Step 7 — Send the Digest to Telegram

The final node delivers the formatted summary to your Telegram chat.
  1. Add a Telegram node and set the operation to Send Message.
  2. Select the Telegram (Personal) credential you created in Step 2.
  3. Set Chat ID to the chat ID you retrieved from the getUpdates API call.
  4. In the Text field, reference the AI output — typically {{ $json.text }} or the field your LLM Chain returns.
  5. Configure additional options:
    • Parse Mode: Markdown (enables Telegram legacy Markdown rendering)
    • Append n8n Attribution: OFF (removes the "Sent with n8n" footer)
    • Reply Markup: None

Step 8 — Test End-to-End and Publish

Run the full workflow manually to verify the message arrives correctly before activating it.
  1. Click Execute Workflow to trigger a manual run.
  2. Check your Telegram app — the digest message should arrive with bold text rendering correctly (not showing raw asterisks).
  3. Verify the format looks clean: subject lines bold, no n8n footer, no broken Markdown symbols.
  4. If bold text is not rendering, go back to the AI prompt and confirm the *bold* rule is stated explicitly — the AI will default back to double asterisks if the instruction is vague.
  5. Once the test passes, click Publish (toggle the workflow to Active) — the workflow will now run automatically every day at 6 PM.

Production tip — After going live, check the workflow after the first 1-2 real scheduled runs to confirm the digest arrives on time and the format still looks right. Real email content is messier than test data and may expose edge cases in the Code node's whitespace normalization or the AI's formatting output.

Key Lessons from This Session

  1. Always verify field names after each n8n update. Simplify=ON output changed between versions — fields assumed to exist (headers.from, headers.subject) were absent in the actual output. Execute a test step and inspect real field names before writing downstream expressions.
  2. Telegram uses legacy Markdown, not standard Markdown. Bold is *text*, not **text** — you must state this rule explicitly in your AI prompt or the message will render incorrectly.
  3. Use Simplify=OFF when you need full email headers. Simplify=ON only exposes a limited set of fields; sender and subject require the full raw payload.
  4. Set Code node to "Run Once for All Items" when aggregating. Without this setting, the node processes items individually and cannot merge them into a single batch for the AI prompt.
  5. Explain terms before building. "Daily digest" is not obvious to all learners — define domain terms before jumping into configuration steps.
  6. Don't activate a new workflow before completing prerequisite steps. In this session, the email classifier workflow (T2-B4-Email-Classifier) needed to be published first before building the digest that depends on its labeled output.

Conclusion:

In this n8n tutorial, we built a complete 4-node daily digest pipeline — Schedule Trigger → Gmail Get Many → Code batch merge → AI summarize → Telegram Send — that runs automatically every evening without any manual action. This is a solid real-world example of n8n workflow automation: it combines scheduling, API data fetching, AI processing, and messaging into a single active pipeline. Next up in the series, we move into Week 3 — connecting Google Sheets with AI to auto-log expenses, capture leads, and generate weekly KPI reports.

If you have any questions, feel free to leave a comment below. Thank you!

Tags: n8n telegram notification, n8n tutorial, n8n workflow automation, email digest automation, n8n gmail integration, telegram bot n8n, n8n schedule trigger, n8n AI summarization

Maybe you are interested!

Arc Browser Now Available on Windows 10, ARM Version Coming Soon

Arc Browser Now Available on Windows 10, ARM Version Coming Soon

Updated August 2: Arc Browser launches on Windows 10, with ARM support on the horizon

Arc Browser, an innovative alternative to mainstream web browsers, finally arrived on Microsoft's platform earlier this year. Initially, the rollout was limited to Windows 11 users only. However, the developers behind Arc didn't abandon Windows 10 users—they committed to bringing the browser to the aging operating system. After several months of development, Arc Browser is now officially available for Windows 10.

Windows 10 users can now download Arc Browser as long as their system runs version 1901 or later. Keep in mind that not every Windows 10 machine will support Arc. The browser requires processors that support the BMI2 instruction set architecture. This means older Intel processors from before the Haswell generation, as well as AMD chips predating the Excavator architecture, won't run the browser.

Currently, Arc doesn't support ARM-based processors, so devices like the Surface Pro 11 or Surface Laptop 7 cannot use the browser. The good news: the development team is actively working on a native ARM version of Arc. ARM support is simply a matter of time.

Arc Browser is now available free of charge on macOS, iOS, iPadOS, Windows 11, and Windows 10. Future updates will introduce an ad blocker, anti-tracking features, and other useful additions. You can download Arc from the official website.


After much anticipation, the rising Arc Browser platform is now available to all Windows 11 users worldwide. Originating from macOS and iOS, Arc stands out from today's modern browsers through its minimalist interface and an array of intelligent personalization features. Currently in closed beta, Arc is available for free to all Windows users globally who want to explore what the browser offers.

Early feedback from Windows beta testers has been largely positive. While the interface takes some getting used to and customization, Arc delivers a clean browsing experience focused on simplicity—free from the clutter and unnecessary features found in many popular browsers today.

Built on Chromium, Arc's compatibility is a non-issue for users. You can access hundreds of thousands of Chrome extensions without any problems. Interestingly, Arc for Windows was built using Swift—Apple's programming language for macOS and iOS—rather than the typical C++. The Arc development team invested considerable effort porting the browser from macOS to Windows. They now hope to encourage other developers to adopt Swift instead of C++, which powers Chrome and Edge.

Despite being written in Swift, Arc for Windows doesn't feel like a direct port of the macOS version. It uses native Windows frameworks, giving you a genuine Windows 11 interface with familiar menus, buttons, and the Mica design language (with Acrylic support for those preferring a more transparent aesthetic).

At the heart of Arc's experience is a feature called Spaces. These are separate browsing environments tailored to different needs—work, entertainment, and more. Spaces appear in the browser's left sidebar, and you can switch between them seamlessly by swiping left or right on your trackpad. Additional conveniences include split view mode, tab groups, vertical tabs, and customization options.

Another clever feature: while browsing, you can hold Shift and click any link to open it in a quick preview window. The linked content displays instantly without creating new tabs, then closes when you're done. This makes scanning content incredibly efficient and is one of Arc's most appreciated features.

Today's release marks just the beginning for Arc. In their announcement, the developers indicated plans to add more features to the Windows version, bringing it closer to parity with the macOS experience, expanding Windows 10 support, and much more.

Source: Quantrimang.com

n8n tutorial - Lesson 07: Build an AI Email Classifier with n8n

n8n tutorial - Lesson 07: Build an AI Email Classifier with n8n

Hi everyone, in this post we're building two production-grade email automation pipelines in n8n: an AI classifier that labels incoming Gmail messages every 15 minutes, and an AI draft reply generator triggered on demand. This is Session 7 of the n8n Workflow Automation Tutorial series — and it's one of the most dense, practical sessions yet.

How to do:

Step 1 — Create the Gmail Labels for Classification

Before building either workflow, you need the destination labels ready in Gmail so the Gmail Add Label nodes have valid targets.
  1. Run your existing T2-B3-Setup-Labels workflow (or create labels manually in Gmail) to ensure these six labels exist: n8n/Quan-trọng, n8n/Chờ-trả-lời, n8n/Hoá-đơn, n8n/Newsletter, n8n/Spam-marketing, n8n/Đã-draft.
  2. In Gmail, go to Settings → See all settings → Labels and confirm each label is set to Show.
  3. Note: the label counter next to each label shows unread count only, not total messages — so n8n/Đã-draft may show zero even after messages are labeled, because drafted emails are typically read.

Note — If you already ran T2-B3-Setup-Labels in a previous session, just run it one more time with the new n8n/Đã-draft entry added. You don't need to recreate the other five labels.

Step 2 — Build the Email Classifier Workflow (T2-B4-Email-Classifier)

This 10-node workflow runs on a 15-minute schedule and automatically labels every new unread email using Claude AI — the core of your n8n email automation setup.
  1. Create a new workflow named T2-B4-Email-Classifier.
  2. Add a Schedule Trigger node. Set the interval to 15 minutes.
  3. Add a Gmail → Get Many node with these settings:
    • Query: is:unread -label:n8n/Quan-trọng -label:n8n/Chờ-trả-lời -label:n8n/Hoá-đơn -label:n8n/Newsletter -label:n8n/Spam-marketing
    • Simplify: ON
    • Limit: 10 (or your preferred batch size)
  4. Add an Edit Fields node named "Filter 4 Core Fields". Map only these four fields: id, from, subject, snippet.
  5. Add a Basic LLM Chain node named "Classify Email" with these settings:
    • Model: Claude Haiku 4.5
    • Temperature: 0
    • Prompt format: XML-style with 5 few-shot examples
    • Attach an Output Parser targeting the field {category}
  6. Add a second Edit Fields node named "Merge ID + Category". Map both id (from the Filter node) and category (from the LLM output) into one item.
  7. Add a Switch node named "Route by Category" with 5 output branches:
    • Branch 1: category equals Quan-trọng
    • Branch 2: category equals Chờ-trả-lời
    • Branch 3: category equals Hoá-đơn
    • Branch 4: category equals Newsletter
    • Branch 5: category equals Spam-marketing
    • Enable Fallback output for unmatched items.
  8. Connect each branch to its corresponding Gmail → Add Label node (5 nodes total), passing the id field as the message identifier.

Tip — Do NOT activate this workflow immediately after testing. Run it manually for 1–2 days first and verify in Gmail that no personal emails are incorrectly labeled as Spam-marketing. Only activate scheduled execution after you're confident in the AI classification accuracy.

Step 3 — Understand How Gmail's Filter + Limit Works

A common misconception about the Gmail Get Many node is how filtering and the Limit setting interact — getting this wrong leads to confusing results.
  1. Gmail does NOT fetch emails first and then filter on n8n's side.
  2. The query string (e.g., is:unread -label:n8n/Quan-trọng) is sent to Gmail's server, which filters the entire inbox first, builds a matching pool, then returns the first N items up to your Limit.
  3. So setting Limit to 10 with a 5-label exclusion filter returns 10 emails that match all conditions — not "10 emails minus excluded ones." This is the standard behavior across search APIs (Gmail, Google Sheets, YouTube, SQL — all work the same way).

Note — If you expect 9 results because "10 minus 1 excluded," you're thinking of client-side filtering. Gmail's -label: syntax is server-side — the excluded emails never enter the result pool at all.

Step 4 — Configure the AI Prompt with Output Parser (Not Just Prompt Instructions)

Getting the LLM to return clean, structured JSON requires more than telling it "return JSON only" — this is a critical lesson for any n8n workflow automation project.
  1. In the Basic LLM Chain node, write a system prompt that:
    • Defines the 5 valid category values
    • Uses XML-style formatting to separate examples clearly
    • Includes 5 few-shot examples showing input (subject + snippet) → output (category value only)
  2. Even with a clear prompt saying "return only the category word, no JSON, no explanation," Claude Haiku 4.5 may still wrap output in ```json...``` blocks and add a Explanation paragraph — this was verified across 10/10 test emails.
  3. The reliable fix: always attach an Output Parser to the LLM Chain node. The Output Parser enforces the schema and strips all markdown wrapping automatically.
  4. Rule: if the LLM output needs to feed into a downstream node (Switch, Edit Fields, etc.), always use Output Parser — never rely on prompt instructions alone.

Production tip — "Prompt-only" output control (Method 1) is unreliable even with temperature=0 and explicit instructions. Output Parser (Method 2) is the only approach you should use in production workflows where downstream nodes depend on structured data.

Step 5 — Understand the Snippet Field vs. Full Email Body

When you set Simplify to ON in the Gmail node, the available content fields change — knowing which field to use for AI classification prevents silent accuracy failures.
  1. The three content fields Gmail returns are:
    • snippet — preview text, approximately 200 characters (50–100 tokens). Available with Simplify ON.
    • text — full plain-text body. Requires Simplify OFF.
    • html — full HTML body. Requires Simplify OFF.
  2. snippet is sufficient for classification in most cases, but fails in three scenarios:
    • Emails where the subject is generic (e.g., "Hi") and the key context is in the body
    • Invoices and receipts where the amount/vendor appears mid-body
    • Newsletters where the snippet is just a logo alt-text or header
  3. Fallback strategy: if snippet-based classification gives low confidence results, switch Simplify to OFF and use text instead — but remember to re-check your field mappings in all downstream Edit Fields nodes after toggling Simplify.

Note — Every time you toggle the Simplify switch on a Gmail node, click Execute Step and re-inspect the JSON tab. The available fields change significantly between ON and OFF states.

Step 6 — Build the Draft Reply Workflow (T2-B5-Email-Drafter)

This 7-node workflow runs manually and generates AI-written draft replies for all emails labeled "Awaiting Reply," then marks them as drafted to prevent duplicates — a key n8n email automation pattern.
  1. Create a new workflow named T2-B5-Email-Drafter.
  2. Add a Manual Trigger node (do not use Schedule — you want full control over when drafts are generated).
  3. Add a Gmail → Get Many node with these settings:
    • Query: label:n8n/Chờ-trả-lời -label:n8n/Đã-draft
    • Simplify: OFF (required to get threadId and text)
    • Limit: 5
  4. Add an Edit Fields node named "Filter Fields for Draft". Map these six fields: id, threadId, from_name, from_email, subject, text.
  5. Add a Basic LLM Chain node named "AI Draft Reply" with these settings:
    • Model: Claude Haiku 4.5
    • Temperature: 0.7
    • Max tokens: 1024
    • 5 few-shot examples showing real email → reply pairs in your writing style
    • Output Parser targeting {subject_reply, body_reply}
  6. Add a Gmail → Create Draft node:
    • Subject: map from subject_reply
    • Message: map from body_reply
    • Thread ID: set to {{ $('Filter Fields for Draft').item.json.threadId }} — use threadId, NOT id
  7. Add a Gmail → Add Label node:
    • Label: n8n/Đã-draft
    • Message ID: use the original email's id (from the Edit Fields node), NOT the newly created draft's ID

Production tip — The -label:n8n/Đã-draft exclusion filter in Step 3 is your deduplication guard. Run the workflow a second time after the first run — it should return 0 items because all processed emails are already labeled. If it still returns emails, check that the Add Label node is targeting the original email id correctly.

Step 7 — Fix the id vs. threadId Production Bug

Using the wrong ID field when creating Gmail drafts is a subtle bug that causes replies to appear as new conversations instead of continuing the thread — catch it before going to production.
  1. Understand the Gmail data model:
    • Every individual email message has its own unique id
    • All messages in the same conversation share one threadId
  2. If you pass id into the Gmail Create Draft node's Thread ID field, Gmail may create the draft as a standalone new message rather than a reply in the existing thread.
  3. The correct approach:
    • In Edit Fields "Filter Fields for Draft", always map threadId as a separate field
    • In Gmail Create Draft, use {{ $('Filter Fields for Draft').item.json.threadId }} for the Thread ID field
    • Keep id mapped separately — you still need it for the Add Label node

Note — This is a database-design-level insight: one thread, many messages, one shared threadId. Always verify your draft is attached to the correct thread in Gmail by opening the draft and confirming it appears inside the original conversation.

Step 8 — Handle No-Reply Emails Gracefully

AI will attempt to draft replies to no-reply addresses unless you filter them out — here are three approaches, listed from simplest to most robust.
  1. Method 1 — Gmail filter (simplest): Add -from:noreply to your Gmail Get Many query string. This is fast and prevents no-reply emails from entering the pipeline at all.
  2. Method 2 — AI decision flag: Add a should_reply boolean field to the LLM output schema. If the AI returns false, route that item to a No Operation branch instead of Create Draft.
  3. Method 3 — Pre-classify in Step 4: In the T2-B4-Email-Classifier workflow, ensure that automated system emails (security alerts, receipts from noreply addresses) are classified into Hoá-đơn or Spam-marketing — not Chờ-trả-lời. This prevents them from ever reaching the drafter workflow.
  4. Production recommendation: combine Method 1 + Method 3. Method 1 is a safety net; Method 3 is the correct architectural fix.

Note — In testing, when AI received a Google Security Alert email and the schema required a body_reply output, the model correctly recognized it couldn't reply — but instead of an error, it output instructions addressed to the user explaining why no reply was needed. The schema was satisfied but the output was wrong. This is why filtering upstream is safer than relying on AI judgment for structural pipeline decisions.

Step 9 — Debug Workflows Using Execute Step Correctly

The Execute Step and Execute Workflow buttons behave differently in n8n — misunderstanding this causes confusing debug results.
  1. Execute Step on any non-trigger node traces backwards through all upstream nodes and runs the full pipeline up to and including that node. It does NOT fan out to sibling branches.
  2. If you click Execute Step on the Gmail Add Label "Newsletter" node and it shows 0 items processed, that is correct behavior — it means no emails were routed to that branch, not that the node failed.
  3. Execute Workflow (or clicking Test Workflow at the top) runs the entire workflow from the trigger node downward, including all branches simultaneously.
  4. When testing with a Schedule Trigger, clicking Execute Workflow bypasses the schedule condition and emits a [{}] placeholder item so the rest of the workflow can run. This is standard behavior for all trigger node types in n8n.

Step 10 — Customize the Few-Shot Examples in the Draft Workflow

The AI draft quality depends directly on the few-shot examples you provide — replace placeholder templates with your real emails for best results.
  1. In the Basic LLM Chain "AI Draft Reply" node, locate the 5 few-shot example pairs currently using placeholder templates.
  2. Replace each pair with a real email you received + the actual reply you sent, formatted as:
    • Input: sender name, subject line, email body (shortened)
    • Output: your actual reply subject and body
  3. Choose examples that cover different tones and scenarios: a quick acknowledgment, a detailed answer, a polite decline, a follow-up, and a scheduling reply — this gives the AI range to match context.
  4. After replacing examples, run the workflow manually on 2–3 test emails and verify the tone and style match your writing before using it regularly.

Tip — This is the difference between Option B (generic template few-shots) and Option A (your real email pairs). Option A gives you drafts that sound like you wrote them. The time investment of collecting 5 real pairs is small compared to the quality improvement.

Key Lessons from This Session

  1. Always use Output Parser when LLM output feeds a downstream node. Prompt-only JSON control is unreliable even with temperature=0 and explicit instructions — verified across 10 emails with Claude Haiku 4.5.
  2. Gmail server-side filtering and client-side filtering are completely different. The -label: query filters before the Limit is applied, so Limit=10 always returns 10 matching items, never "10 minus excluded."
  3. Use threadId, not id, for the Gmail Create Draft Thread ID field. Each message has a unique id; all messages in a conversation share one threadId.
  4. Deduplicate with label exclusion filters, not workflow state. The -label:n8n/Đã-draft query pattern is simple, reliable, and self-documenting.
  5. Filter no-reply emails at the Gmail query level, not the AI level. Combine -from:noreply in the query with correct classification in the upstream classifier workflow.
  6. Toggle Simplify ON/OFF only when you re-inspect all downstream field mappings. Simplify changes which fields are available — missing a re-check breaks Edit Fields nodes silently.
  7. Execute Step traces upstream; it does not run sibling branches. Zero items on a Switch branch means no emails were routed there — not a node failure.
  8. Do not activate scheduled workflows until you manually verify AI accuracy for 1–2 days. A misclassified personal email in Spam-marketing is a production incident that erodes trust in the automation.

Conclusion:

In this session, you built two complete n8n email automation pipelines: a 10-node AI email classifier running on a 15-minute schedule, and a 7-node AI draft reply generator with deduplication. Along the way, you resolved real production-grade issues — Output Parser enforcement, the id vs. threadId bug, no-reply edge cases, and Gmail's server-side filter behavior — all of which apply to any advanced n8n workflow automation project. In the next session, we'll complete the trilogy by adding a daily 6 PM digest that summarizes important emails and sends them to Telegram, then combine all three pipelines into one unified AI email assistant system.

If you have any questions, feel free to leave a comment below. Thank you!

Tags: n8n email automation, n8n tutorial, n8n workflow automation, Gmail AI classifier, n8n Claude integration, email draft automation, n8n Output Parser, n8n beginner to advanced

Maybe you are interested!

n8n tutorial - Lesson 06: Connect Gmail to n8n: OAuth Setup & Reading Emails

n8n tutorial - Lesson 06: Connect Gmail to n8n: OAuth Setup & Reading Emails

Hi everyone, in this post we are going to walk through how to set up the n8n Gmail integration from scratch — enabling OAuth, reading emails, and applying labels using real workflow steps. This is Session 6 of our n8n Workflow Automation Tutorial series, and it is where Week 2 kicks off with some genuinely useful, production-ready patterns.

How to do:

Step 1 — Enable Gmail API and Set Up OAuth in Google Cloud Console

Before n8n can talk to your Gmail, you need to enable the Gmail API inside Google Cloud Console and add the correct OAuth scope.

  1. Go to Google Cloud Console and open your project. In this tutorial we use a project called Default Gemini Project — you can use any existing project you already have.
  2. In the left menu, go to APIs & Services → Library, search for Gmail API, and click Enable.
  3. Now go to APIs & Services → OAuth Consent Screen. Scroll down to the Data Access section and click Add or Remove Scopes.
  4. Add the scope https://mail.google.com/. This is a restricted scope, but if your app is still in Testing mode and your account is added as a Test User, Google will let you authorize it without a full verification review.
  5. Save the consent screen settings.

Tip — Reuse your existing OAuth Client: If you already set up an OAuth Client ID for Google Sheets in a previous session (we called ours n8n-sheets-client), you do not need to create a new one. One OAuth Client can cover multiple Google APIs. Just reuse the same Client ID and Client Secret — you will simply sign in again and Google will request the new Gmail scope during authorization. This follows a clean convention: one OAuth Client, many Google APIs.

Step 2 — Create the Gmail Credential in n8n

  1. Open n8n and go to Credentials → Add Credential. Search for Gmail OAuth2.
  2. Name the credential Gmail (Personal) (or any name that helps you identify it).
  3. Paste your Client ID and Client Secret from the OAuth Client you set up in Google Cloud Console.
  4. Click Sign in with Google. A Google authorization window will appear. Select your account, accept the Gmail scope, and click Allow.
  5. You should see a green Connection Tested Successfully message. Click Save.

Step 3 — Read Emails with Gmail Get Many

Now let's build a simple playground workflow to read emails. Create a new workflow and name it T2-B2-Gmail-Playground.

  1. Add a Manual Trigger node as the starting point.
  2. Add a Gmail node. In the new n8n UI, instead of selecting a Resource and Operation separately, you will see a flat Action picker. Choose Get Many.
  3. Connect it to your Gmail credential.
  4. First test run — Simplify ON, Limit 5: Leave Simplify turned on and set Limit to 5. Click Execute Node. You will get a clean, compact output with just the core fields you need.
  5. Second test run — Simplify OFF, Limit 5: Turn Simplify off and run again. Here is something important to know: the raw Gmail API returns a nested MIME structure with fields like payload and internalDate. But n8n pre-processes this for you. Even with Simplify off, the output is already flattened into clean fields: headers, text, html, attachments, and a label array where each item has both an id and a human-readable name. Do not assume the raw Gmail API structure — always run the node first and check the JSON tab to see what n8n actually gives you.
  6. Third test run — Filter unread emails: In the Filters section, add a search query: is:unread. Run it again. Now you only get unread emails, and you will see the UNREAD label in the label array.

Production tip — What to feed an AI classifier: When you plan to pass email data to an AI model for classification, only send these three fields: headers.from, headers.subject, and snippet. Together they cost roughly 150 tokens per email. Avoid sending the html field — it can be 5,000 to 10,000 tokens per email and will burn through your AI budget fast. We will use this pattern in the email classification pipeline coming in the next session.

Step 4 — Create Custom Gmail Labels

To organize emails processed by your n8n workflow, create a dedicated set of labels in Gmail directly from n8n. Create a new workflow named T2-B3-Setup-Labels.

  1. Add a Manual Trigger node.
  2. Add a Gmail node and choose the action Create Label.
  3. In the Label Name field, type the name of the first label. Run the workflow. Then change the name and run again for each label you need. We created five labels for our Week 2 project:
    • n8n/Important
    • n8n/Awaiting Reply
    • n8n/Invoice
    • n8n/Newsletter
    • n8n/Marketing Spam
  4. Notice the n8n/ prefix. Gmail supports nested labels using a forward slash. Using a prefix like n8n/ keeps all your automation labels grouped together and separate from your personal labels. This is a clean naming convention worth adopting from the start.

Step 5 — Add a Label to an Email

Now let's test adding a label to a real email. Go back to your T2-B2-Gmail-Playground workflow and extend it.

  1. After the Gmail Get Many node, add another Gmail node and choose the action Add Label.
  2. Set Limit to 1 in the Get Many node so you only process one email for this test.
  3. In the Add Label node, set Message ID to {{ $json.id }} to reference the email from the previous node.
  4. Set Label to n8n/Important.
  5. Click Execute Workflow.
  6. Check the output of the Add Label node. You will notice it returns raw label IDs like Label_1 — it does not enrich the label with a human-readable name the way Get Many does. This is a known difference between operations in the same node. Always check the JSON tab for each operation independently.
  7. Go to your Gmail inbox in the browser and open that email. You should see the n8n/Important label chip attached to it. That confirms the operation worked correctly. Do not rely only on the n8n output panel — verify in the actual service when the output is ambiguous.

A Quick Note on Cost and Quota

One practical question that comes up right after connecting Gmail: does calling the Gmail API cost anything? The short answer is no. The Gmail API is completely free. Google does enforce quota limits — 250 units per second per user and around 1 billion units per day per project — but for personal automation these limits are essentially never a concern.

The real cost in any n8n Gmail workflow is the AI tokens you spend on classification or analysis. For a personal email automation running every 15 minutes and processing a moderate volume, expect something in the range of a dollar or two per month. Keep this in mind before you build a large pipeline: always estimate your AI token cost first, and keep the data you send to the AI model as small as possible.

Key Lessons from This Session

  1. Always run the node and check the JSON tab first. Do not trust the Gmail API documentation to predict what n8n gives you. n8n flattens and enriches the raw API response, and the output can look very different from what the original API returns.
  2. Different operations on the same node can return different shapes. Gmail Get Many enriches labels with names. Gmail Add Label returns raw IDs. Check each operation independently.
  3. The new n8n UI uses a flat Action picker instead of separate Resource and Operation dropdowns. If your UI looks different from older tutorials, this is why.
  4. One OAuth Client can cover multiple Google APIs. You do not need a new Client ID for every Google service you connect.

What Comes Next

In the next session of this n8n tutorial series, we will build a full end-to-end email classification pipeline. It will use a Schedule Trigger running every 15 minutes, pull only unread and unclassified emails, pass the minimal fields to an AI model for classification, and then route each email to the correct label using a Switch node. That is where all the pieces we set up today come together into a real automated workflow.

Conclusion:

Setting up the n8n Gmail integration is straightforward once you understand the OAuth scope requirement and the way n8n flattens Gmail's raw API response. With the credential in place and these basic read and label operations working, you now have a solid foundation for building a fully automated email management workflow as part of your n8n workflow automation practice.

If you have any questions, feel free to leave a comment below. Thank you!

Tags: n8n gmail integration, n8n tutorial, n8n workflow automation, gmail oauth n8n, n8n email automation, google cloud oauth setup, n8n gmail labels, n8n beginner tutorial

Maybe you are interested!

n8n tutorial - Lesson 05: Comparing AI Models in n8n: Claude vs Gemini vs ChatGPT

n8n tutorial - Lesson 05: Comparing AI Models in n8n: Claude vs Gemini vs ChatGPT

Hi everyone, in this post we are going to compare three major AI models — Claude, Gemini, and ChatGPT — inside a real n8n workflow. This is part of our ongoing n8n Workflow Automation Tutorial series, and by the end you will have a working benchmark workflow that runs all three models in parallel and logs the results to Google Sheets.

This post is based on a real hands-on session from Week 1 of the series. We built the workflow T1-B13-Benchmark-3-Models end-to-end and ran into several real bugs and gotchas along the way. Everything you read here comes from actual production-grade experience.

Why Compare AI Models in n8n?

When you are building n8n workflow automation for real projects, picking the right AI model matters. Claude, Gemini, and OpenAI (ChatGPT) each behave differently in terms of output quality, response format, latency, and reliability. Running a benchmark inside n8n lets you see the differences side by side on your exact prompt and use case — not just on generic benchmarks from a marketing page.

This n8n AI models comparison approach is also reusable. Once the workflow is built, you can swap in any topic and re-run it anytime you want to evaluate model outputs for a new task.

What the Final Workflow Looks Like

The completed workflow T1-B13-Benchmark-3-Models has 6 nodes in this order:

Manual TriggerSet Topic (Edit Fields) → 3 AI branches in parallel (Claude, Gemini, OpenAI) → MergeBuild Row (Code node) → Google Sheets Append

Results are written to a Google Sheet named T1-Benchmark-3-Models, tab Results, with columns: topic, claude_output, gemini_output, openai_output, timestamp.

How to do:

  1. Step 1 — Set up your Google Sheet

    Create a new Google Sheet and name it T1-Benchmark-3-Models. Inside it, rename the first tab to Results. Add these 5 column headers in row 1: topic, claude_output, gemini_output, openai_output, timestamp. Keep this sheet open — you will need the Spreadsheet ID from the URL later.

  2. Step 2 — Set up Google Sheets OAuth credential in n8n

    This is a 5-phase process. Go to Google Cloud Console and open your project (in the session we used Default Gemini Project). Enable both Google Sheets API and Google Drive API — you need Drive enabled too because n8n uses it to list and find your Sheet.

    Next, go to OAuth Consent Screen, select External, and keep it in Testing mode. Add yourself as a Test User. One important trap here: if you accidentally click Publish app, the status changes to "In production" and the Test Users section disappears. Fix this by clicking Back to testing.

    Then create an OAuth Client ID named n8n-sheets-client. Copy the Redirect URI from n8n and paste it into the Authorized Redirect URIs field in Google Cloud. Finally, go back to n8n, create a new credential called Google Sheets (Personal), paste in your Client ID and Client Secret, then click Sign in with Google. You will see a warning that says "App isn't verified" — click Advanced and continue. That is expected behavior for apps in Testing mode.

  3. Step 3 — Create the workflow and add the Manual Trigger and Set Topic nodes

    Create a new workflow and name it T1-B13-Benchmark-3-Models. Add a Manual Trigger node as the start. Then add an Edit Fields node, rename it Set Topic, and add one field: key = topic, value = your default test topic. In the session we used "How to effectively self-learn AI Automation as a beginner" as the default topic.

  4. Step 4 — Add 3 parallel AI branches

    This is where the n8n AI models comparison actually happens. You need to add three separate AI nodes — one for Claude (Anthropic), one for Gemini, one for OpenAI — all connected directly from the Set Topic node output.

    Important trap: n8n's + button always belongs to whichever node is currently selected. If you click + without having Set Topic selected, n8n will create a sequential connection instead of a parallel branch. To add parallel branches correctly, click on the Set Topic node first, then click its + button, add the first AI node, then go back and click Set Topic again before adding the next one.

    Use the same prompt for all three nodes, asking for a response of 120-150 words. This keeps the comparison fair.

    For Gemini: during testing we found that gemini-2.0-flash had a limit:0 error, so switch to gemini-2.5-flash instead. Gemini on the free tier also throws 503 errors more often than Claude or OpenAI — this is because free tier has lower priority, 2.5-flash is in high demand, and if you are in Vietnam you are hitting US peak hours. If you get a 503, just retry the node.

  5. Step 5 — Add a Merge node

    Add a Merge node and connect all three AI branch outputs into it. This collects the results from Claude, Gemini, and OpenAI into a single stream before building the row.

    One thing to keep in mind: n8n runs these three branches sequentially by default, not in true parallel. The "parallel branches" in n8n are logical, meaning they share the same single-threaded executor. If you need real parallel execution you would use a Code node with Promise.all or a sub-workflow. For a benchmark like this, sequential execution is fine.

  6. Step 6 — Build the row with a Code node

    Add a Code node after Merge and rename it Build Row. This node assembles one object with all four values (topic, claude_output, gemini_output, openai_output) plus a timestamp, ready to be appended to your Sheet.

    Two bugs we hit here during the session: First, sibling nodes (branches at the same level) cannot reference each other using $('NodeName') directly — you need to reference them from a downstream node like this Code node instead. Second, the OpenAI output field is text, not output. This changed in a recent n8n update — n8n now standardizes all three providers to use the text field. The lesson: never trust convention alone. Always check the actual JSON output in the JSON tab of the node to verify the field name before writing your code.

    Here is a simple code structure for the Build Row node:

    Reference each AI node using $('Claude').first().json.text, $('Gemini').first().json.text, and $('OpenAI').first().json.text. The .first() method is required because every node output in n8n is an array of items — you need to call a method to select which item you want.

  7. Step 7 — Append to Google Sheets

    Add a Google Sheets node, set the operation to Append, and select your Google Sheets (Personal) credential. Use the Resource Locator to find your spreadsheet. Watch out for a common trap here: there are two different IDs involved. The Spreadsheet ID is the long string in the URL of your Google Sheet. The Sheet ID (gid) is a separate number that identifies which tab inside the spreadsheet. Make sure you are entering each one in the correct field.

    Set the mapping mode to Map Automatically so n8n matches your output field names to your column headers automatically. Run the workflow and check your Sheet — you should see a new row with all four values plus the timestamp.

  8. Step 8 (Bonus) — Add an AI Judge to pick the best model

    This is an optional bonus step. After the Merge node, add another AI node using Claude Haiku (Anthropic) and configure it to read all three outputs and decide which model gave the best answer.

    There are three fixes you must apply to make this work correctly. First, add a Limit (1) node between Merge and the Judge node. Without it, Merge outputs 3 items, the Judge runs 3 times, and because AI is non-deterministic you get 3 different evaluations — which defeats the purpose. The Limit node here is not filtering data; it is acting as a barrier sync, making sure the Judge fires only once. The Judge reads its input data from $('NodeName') references anyway, not from the wire data, so First/Last/Middle all give the same result.

    Second, add an Output Parser (Structured, Generate from Example) on the Judge node with the schema {best_model, reason}. Without this, the AI returns a 300-word essay instead of a structured value, and your Sheet column breaks.

    Third, set Sampling Temperature = 0 on the Judge's chat model sub-node to make the evaluation deterministic.

Key Takeaways from This n8n AI Models Comparison

After running this workflow several times, here are the practical differences we observed:

Claude gave the most consistently structured and readable output. Gemini was fast when it worked but had the most reliability issues on the free tier (503 errors, model version resets). OpenAI was the most stable and predictable. For production n8n workflow automation, stability matters as much as output quality — a 503 that breaks your workflow at 2 AM is worse than a slightly shorter response.

One thing that came up in this session that is worth sharing: when you build an n8n tutorial project like this benchmark, you learn far more from the bugs than from the steps that work on the first try. The Gemini model version resetting, the OpenAI field name change, the parallel branch trap with the + button — none of these show up in official documentation, but all of them will hit you in real projects.

Conclusion:

In this post we walked through building a full n8n AI models comparison workflow that benchmarks Claude, Gemini, and ChatGPT on the same prompt and logs the results to Google Sheets. This is a practical, reusable pattern you can apply to any n8n workflow automation project where you need to evaluate model outputs before committing to one provider.

If you have any questions, feel free to leave a comment below. Thank you!

Tags: n8n tutorial, n8n workflow automation, n8n AI models comparison, Claude vs Gemini vs ChatGPT, n8n Google Sheets integration, n8n beginner tutorial, AI automation workflow, n8n benchmark workflow

Maybe you are interested!

n8n tutorial - Lesson 04: n8n Expressions & Built-in Variables: The Complete Guide

n8n tutorial - Lesson 04: n8n Expressions & Built-in Variables: The Complete Guide

Hi everyone, in this post we're diving deep into one of the most powerful features in n8n — expressions and built-in variables. If you've been following our n8n workflow automation tutorial series, this is the session where things really start to click. We'll walk through real hands-on examples from our T1-B8-Expressions-Playground workflow, cover the five core expression skills every n8n user needs, and flag a few tricky bugs you'll want to avoid from the start.

What Are n8n Expressions?

In n8n, an expression is a piece of dynamic code you write inside double curly braces {{ }}. Instead of typing a fixed value into a field, you write an expression that pulls live data from your workflow — like a field from the previous node, the current timestamp, or even data from a node further up the chain. This is what makes n8n workflow automation genuinely flexible rather than just mechanical.

Expressions in n8n follow JavaScript syntax, which means you can do real programming inside them — string methods, math operations, conditionals, and more. This complete n8n expressions guide will show you exactly how each piece works with real examples you can copy into your own workflows.

The Workflow We're Using

For this session, we built a workflow called T1-B8-Expressions-Playground. It runs in this order: Manual TriggerSeed DataBuild ProfileTransform DataAudit Report. Each node in this chain uses a different expression skill so you can see them all working together in context. Let's go through each skill one by one.

How to do:

  1. Step 1 — Use $json to access current item data

    The most basic expression you'll use constantly is $json. This variable gives you access to the JSON fields of the current item being processed. In the Build Profile node, for example, to pull the userId field from the incoming data, you write:

    {{ $json.userId }}

    Click into any field inside a Set or Edit Fields node, switch to Expression mode (click the small expression toggle next to the field), and type your expression. You'll see a live preview of the value on the right side of the editor — this is your best friend when debugging.

  2. Step 2 — Apply JavaScript string methods inside expressions

    Because expressions are JavaScript, you can chain any standard JS string method directly onto a value. In the Build Profile node, we used two common ones:

    {{ $json.name.toUpperCase() }} — converts the name to all caps.
    {{ $json.name.charAt(0) }} — pulls just the first character, useful for initials or avatar labels.

    One important note: you cannot get these methods by dragging and dropping a field from the data panel. Drag-drop only inserts the plain field reference like {{ $json.name }}. To use methods like .toUpperCase() or .charAt(), you have to type them manually. This is a key distinction in the n8n editor that trips up a lot of beginners.

  3. Step 3 — Do math and use Number() to avoid type bugs

    In the Transform Data node, we tried adding two fields together — something like age plus a bonus value. The first attempt used:

    {{ $json.age + 10 }}

    The result was 3010 instead of 40. This happens because n8n sometimes carries field values as strings, and in JavaScript the + operator on strings means concatenation, not addition. So "30" + 10 gives you "3010".

    The fix is simple — wrap your variable in Number() to force it to be treated as a number:

    {{ Number($json.age) + 10 }}

    This is one of the most common bugs in any n8n tutorial on expressions, so write it in your notes now. Whenever you do arithmetic in an expression and the result looks wrong, check whether your values are actually numbers or strings.

  4. Step 4 — Build strings with template literals (backtick syntax)

    Template literals let you mix fixed text and dynamic variables cleanly in one expression. Instead of trying to concatenate strings with +, you use backticks and insert variables with ${ } inside them. In the Build Profile node we built a description field like this:

    {{ `Hello, my name is ${$json.name} and I am ${$json.age} years old.` }}

    The whole expression goes inside the outer {{ }}, and the backtick template lives inside that. This pattern is also exactly what we used in the Build Description Code node in our Switch workflow — combining team, id, title, and status into one formatted string. Template literals make your output readable and easy to maintain.

  5. Step 5 — Reference data from a different node using $node

    Sometimes you need data from a node that isn't the one directly before your current node. For example, in the Audit Report node, we needed to pull data from the Seed Data node, which was several steps back in the chain. The built-in variable for this is $node:

    {{ $node["Seed Data"].json.fieldName }}

    Use the exact node name in quotes inside the square brackets — this is case-sensitive. If your node is named Seed Data with a capital S and D, write it exactly that way. This variable is incredibly useful in complex workflows where data branches and merges and you need to reach back to an earlier step.

  6. Step 6 — Use $now for timestamps and date formatting

    n8n has a built-in variable called $now that gives you the current date and time. You used it in the T1-B7-Schedule-Demo workflow to add a timestamp field with {{ $now }}. In the expressions playground, we went further and formatted the output using the .toFormat() method:

    {{ $now.toFormat('yyyy-MM-dd HH:mm:ss') }}

    The timezone n8n uses locally was confirmed as Asia/Ho_Chi_Minh (UTC+07:00) — this matters if your workflow relies on time comparisons or scheduling. If you're on a cloud instance, check your instance timezone setting in the n8n settings panel because it may default to UTC.

  7. Step 7 — Use $workflow to access workflow metadata

    The $workflow variable gives you metadata about the workflow itself — things like its name and ID. In the Audit Report node, we used it to stamp the report with the workflow name:

    {{ $workflow.name }}

    You can also access {{ $workflow.id }} and {{ $workflow.active }} which returns true or false depending on whether the workflow is currently published and active. This is handy when you're building logging or monitoring workflows that need to identify which workflow they belong to.

  8. Step 8 — Understand drag-drop vs manual typing

    In the n8n expression editor, you can drag a field from the data preview panel on the left and drop it into a field. This inserts a basic reference like {{ $json.fieldName }} automatically. That's great for simple lookups.

    But the moment you want to do anything more — add a method, format a string, do math, or reference another node — you have to type it manually. Drag-drop gives you the raw reference only. Think of drag-drop as a shortcut for simple cases and manual typing as the full tool. Once you get comfortable typing expressions, you'll find you use drag-drop less and less.

  9. Step 9 — Watch out for the "Include Other Input Fields" bug in Set nodes

    This one bit us during the Switch workflow and it directly affects expressions. In the Label Marketing, Label Sales, and Label Engineering Set nodes, the Include Other Input Fields option was set to Selected with only the userId field ticked. This silently dropped all other fields — id, title, and completed — from the output.

    When the Build Description Code node downstream tried to reference $input.item.json.id and $input.item.json.title, they came back as undefined because those fields no longer existed in the data.

    The fix: go back to each Set node, find the Include Other Input Fields setting, and change it from Selected to All. This ensures all fields flow through the node, not just the ones you explicitly ticked. Any time your expressions are returning undefined, check what the upstream nodes are passing through — this setting is one of the most common culprits.

  10. Step 10 — Quick reference: the five built-in variables you'll use most

    To wrap up the practical skills, here's a clean summary of the five variables from this session that you'll use in almost every real workflow:

    $json — Current item's data fields. Example: {{ $json.email }}
    $node["NodeName"].json.field — Data from a specific upstream node. Example: {{ $node["Seed Data"].json.id }}
    $now — Current timestamp. Example: {{ $now.toFormat('yyyy-MM-dd') }}
    $workflow.name — The workflow's name. Example: {{ $workflow.name }}
    Number() — Force a value to be numeric before doing math. Example: {{ Number($json.score) + 5 }}

    Keep this list somewhere accessible. In any n8n tutorial situation — whether you're following along here or troubleshooting your own flows — these five will cover the majority of what you need.

Bonus: Versioning and the Publish Button

One thing that came up during the Schedule Trigger session (Step 7 of this series) that's worth mentioning alongside expressions: when you click Publish in n8n, it creates a snapshot of your workflow. Automated runs use the published snapshot. Manual runs from the editor use your current unsaved version. This means you can safely experiment with expressions in the editor without breaking your live production workflow. The Publish button turns green when the editor matches the published version, and yellow when you have unpublished changes.

Conclusion:

n8n expressions are what separate a basic automation from a truly smart workflow — they let your nodes talk to each other, handle real data dynamically, and react to context instead of just running fixed logic. With the five skills covered in this n8n expressions guide$json, JavaScript methods, Number() for math, template literals, and $node for cross-node data — you have everything you need to build professional-grade workflows as part of your ongoing n8n workflow automation journey.

If you have any questions, feel free to leave a comment below. Thank you!

Tags: n8n expressions guide, n8n tutorial, n8n workflow automation, n8n built-in variables, n8n beginners guide, n8n expressions examples, workflow automation tutorial, n8n $json $now $workflow

Maybe you are interested!

n8n tutorial - Lesson 03: Branching Workflows: IF, Switch & Merge Nodes in n8n

n8n tutorial - Lesson 03: Branching Workflows: IF, Switch & Merge Nodes in n8n

Hi everyone, in this post we are diving into one of the most useful parts of any n8n workflow automation setup — branching logic. You will learn how to use the IF node, the Switch node, and the Merge node in n8n to split, route, and recombine your data like a pro. This is part of our ongoing n8n Workflow Automation Tutorial series, so if you are new here, check out the earlier posts before jumping in.

What Are Branching Nodes in n8n?

When you build real-world automations, not every item should follow the same path. Some tasks are done, some are pending. Some emails are spam, some are not. Branching nodes let you check a condition and send each item down the right path. In this n8n tutorial, we will work through three branching tools: IF, Switch, and Merge, using real workflows from our learning sessions.

How to do:

Part 1 — Using the IF Node to Split Items into Two Paths

  1. Step 1: Open your existing workflow. In our session we used the workflow named T1-B1-Hello-n8n, which already had an Edit Fields node pulling in todo items from an API.

  2. Step 2: Click the + button after the Edit Fields node and search for IF. Add the IF node to your canvas.

  3. Step 3: Inside the IF node, set up your condition. Click Add Condition, choose the field completed, set the operator to is true, and use the expression {{ $json.completed }}. This tells n8n: "if the completed field is true, go left; otherwise go right."

  4. Step 4: Run the workflow. With 10 items in our test, the IF node split them into 3 true (completed tasks) and 7 false (incomplete tasks). You will see two output branches appear on the node — true on the left and false on the right.

  5. Step 5: Add a Set node to the true branch. Rename it Set Done and add a field called status with the value Done.

  6. Step 6: Add another Set node to the false branch. Rename it Set Pending and add a field called status with the value Pending.

Quick tip from our session: You can also use the IF node with Gmail data. For example, set a condition like labelIds contains SPAM to route spam emails into a separate processing path. However, if your data source already supports filtering (like using query parameters in an HTTP Request), it is better to filter at the source rather than using an IF node — this keeps your workflow cleaner and faster.

Part 2 — Using the Switch Node to Route Items into Multiple Paths

  1. Step 1: Create a new workflow and name it T1-B4-Switch-Demo. Add an HTTP Request node, rename it Get 60 Todos, and point it to the JSONPlaceholder todos API. Add a query parameter _limit with value 60. This returns 60 todo items spread across three user IDs: 1, 2, and 3.

  2. Step 2: Click the + button after the HTTP Request node and search for Switch. Add the Switch node and rename it Route by userId.

  3. Step 3: Inside the Switch node, add three rules. For each rule, set the data type to Number, the field to {{ $json.userId }}, the operator to equal, and the values to 1, 2, and 3 respectively. This creates three output branches — one for each user group.

  4. Step 4: Run the workflow. Each branch should receive exactly 20 items (60 items divided by 3 user IDs). The Switch node routes each item to the matching output based on its userId value.

  5. Step 5: Try the Fallback behavior. Change the _limit to 100 and re-run. Now 40 extra items with userId 4 and 5 do not match any rule, so they fall into the Fallback output. This is very useful in production — always plan for unexpected values by handling the Fallback branch.

  6. Step 6: Add a Set node after each branch. Name them Label Marketing, Label Engineering, and Label Sales. In each node, add a field called team with the corresponding team name (Marketing, Engineering, Sales). Make sure to set Include Other Input Fields to All — we will explain why this matters in the Code node section below.

Switch vs IF: Use the IF node when you have two paths (true/false). Use the Switch node when you have three or more possible routes. Think of Switch as a smarter, more scalable version of IF for multi-branch scenarios. Also remember that Switch rule indexes are 0-based — output 0 is the first rule, output 1 is the second, and so on.

Part 3 — Using the Merge Node to Combine All Branches

  1. Step 1: Still inside T1-B4-Switch-Demo, click the + button and search for Merge. Add it to the canvas and rename it Combine All Teams.

  2. Step 2: Inside the Merge node settings, set the Mode to Append and set Number of Inputs to 3. This tells n8n to accept data from three separate branches and join them into one stream.

  3. Step 3: Connect the output of Label Marketing to Input 1 of the Merge node. Connect Label Engineering to Input 2 and Label Sales to Input 3.

  4. Step 4: Run the workflow. The Merge node output should show all 60 items — 20 from Marketing, then 20 from Engineering, then 20 from Sales, joined one after another. In Append mode the data is stacked in order, not mixed together. This is exactly what we expected.

Part 4 — Adding a Code Node After the Merge (Bonus Step)

Once your data is merged, you can process all 60 items together with a Code node. Here is what we did in our session to build a formatted description for each item.

  1. Step 1: Add a Code node after the Merge node and rename it Build Description. Set the mode to Run Once for Each Item and the language to JavaScript.

  2. Step 2: Paste in the following code:

    const item = $input.item.json;
    const desc = `[${item.team.toUpperCase()}] #${item.id} - ${item.title} (${item.status || 'N/A'})`;
    return {
      json: {
        ...item,
        description: desc
      }
    };
    
  3. Step 3: Run the workflow. If you see undefined appearing in the description for fields like id or title, that means your upstream Set nodes dropped those fields. Go back to each of the three Label Set nodes (Label Marketing, Label Engineering, Label Sales) and change Include Other Input Fields from Selected to All. This ensures every field from the original item passes through alongside the new team field.

  4. Step 4: Re-run after the fix. Your output should now show a clean description field on every item, for example: [MARKETING] #1 - delectus aut autem (N/A).

Bug note worth saving: In n8n, when you add a Set node and only select specific fields to include, n8n drops everything else by default. Always double-check the Include Other Input Fields setting — set it to All unless you specifically want to remove fields. This is a very common gotcha for beginners in any n8n workflow automation project.

Quick Reference: IF vs Switch vs Merge

Here is a simple breakdown to help you decide which node to use:

  • IF node — Use when you have exactly two paths: true or false. Great for simple yes/no conditions like "is this task completed?" or "does this email contain SPAM?"
  • Switch node — Use when you have three or more paths. Route items based on a value that can match multiple cases. Always handle the Fallback branch for values that do not match any rule.
  • Merge node — Use to bring multiple branches back together into one data stream. In Append mode it stacks items in order without mixing them.

Conclusion:

In this n8n IF node tutorial, you learned how to split workflow data into two paths with the IF node, route items across multiple branches with the Switch node, and combine everything back together using the Merge node — all key skills for building real-world n8n workflow automation. Keep these three nodes in mind whenever your automation needs to make decisions, and always check your Set node field settings to avoid the "undefined field" bug we caught in our session.

If you have any questions, feel free to leave a comment below. Thank you!

Tags: n8n tutorial, n8n workflow automation, n8n IF node tutorial, n8n Switch node, n8n Merge node, n8n branching workflow, n8n beginner guide, workflow automation tips

Maybe you are interested!

n8n tutorial - Lesson 02: n8n HTTP Request Node: Connect Any API Without Code

Lesson 02: n8n HTTP Request Node: Connect Any API Without Code

Hi everyone, in this post I'll show you how to use the n8n HTTP Request node to pull data from any API — no code required. This is one of the most useful nodes in n8n workflow automation, and once you get the hang of it, you'll use it in almost every workflow you build.

This article is part of the n8n Workflow Automation Tutorial series here on QTitHow.com, taking you from beginner basics all the way to advanced automation. Today we're focusing on a real hands-on example: fetching to-do items from a public API and routing them through multiple nodes. Let's get started.

What Is the n8n HTTP Request Node?

The HTTP Request node in n8n lets you connect to virtually any REST API on the internet — GET, POST, PUT, DELETE, you name it. Think of it as a universal adapter. Whether you're pulling data from a project management tool, a public database, or your own backend, the n8n HTTP Request node handles it without writing a single line of code.

In this n8n tutorial, we'll use the free public API at jsonplaceholder.typicode.com as our data source. It returns fake to-do items — perfect for practice. No API key needed, no setup, just a URL.

How to do:

  1. Create a new workflow
    Open your n8n editor and click + New Workflow in the top left. Name it T1-B4-Switch-Demo (or any name you like). This keeps your workspace organized, especially as you build more workflows in this n8n tutorial series.
  2. Add a Manual Trigger node
    Click the + button on the canvas to add your first node. Search for Manual Trigger and select it. This lets you run the workflow on demand while you're testing — no schedule needed yet.
  3. Add the HTTP Request node
    Click the + button after the Manual Trigger. Search for HTTP Request and add it. Rename this node to Get 60 Todos so it's clear what it does at a glance.
  4. Configure the HTTP Request node
    In the node settings, set the Method to GET. In the URL field, enter:
    https://jsonplaceholder.typicode.com/todos?_limit=60
    The _limit=60 parameter tells the API to return 60 items. Click Execute Node to test it. You should see 60 items come back, each with fields like userId, id, title, and completed. If you see data in the output panel, the connection is working perfectly.
  5. Check the output data
    Look at the output in the right panel. You'll notice the 60 items have userId values of 1, 2, and 3 — 20 items each. This is exactly what we'll use in the next step to route items by team. Understanding your data shape here is key before you connect any more nodes in your n8n workflow automation.
  6. Add a Switch node to route by userId
    Click + after the HTTP Request node. Add a Switch node and rename it Route by userId. In the settings, set the Value to {{ $json.userId }} using the expression editor. Add 3 rules:
    — Rule 1: Number, equal to 1
    — Rule 2: Number, equal to 2
    — Rule 3: Number, equal to 3
    This splits your 60 items into 3 separate output branches, 20 items each. The Switch node is perfect when you have more than 2 routing conditions — more flexible than a plain IF node.
  7. Add a Set node to each branch
    Connect a Set node to each of the 3 Switch outputs. Name them:
    Label Marketing (add field: team = Marketing)
    Label Kỹ thuật (add field: team = Kỹ thuật)
    Label Sales (add field: team = Sales)
    Important: In each Set node, make sure Include Other Input Fields is set to All — not Selected. If you leave it on Selected and only tick one field, you will lose the id, title, and completed fields. This is a real bug that came up during testing — the downstream Code node returned undefined for those fields until this was fixed. Set it to All and the problem disappears.
  8. Add a Merge node to combine all branches
    After the three Set nodes, add a Merge node. Rename it Combine All Teams. Set the Mode to Append and Number of Inputs to 3. Connect the outputs of Label Marketing, Label Kỹ thuật, and Label Sales into the three inputs of this Merge node. When you execute, you'll get all 60 items back in one stream — 20 Marketing, then 20 Kỹ thuật, then 20 Sales, joined in sequence.
  9. Add a Code node to build a description field
    Add a Code node after the Merge. Rename it Build Description. Set the mode to Run Once for Each Item and the language to JavaScript. Paste in this code:

    const item = $input.item.json;
    const desc = `[${item.team.toUpperCase()}] #${item.id} - ${item.title} (${item.status || 'N/A'})`;
    return { json: { ...item, description: desc } };

    This creates a clean description field for each item, like: [MARKETING] #3 - fugiat veniam minus (N/A). Execute the node and check the output — every item should now have the new description field alongside all the original fields.
  10. Test the Fallback behavior (optional but useful)
    Go back to the HTTP Request node and change _limit=60 to _limit=100. Execute the workflow again. The extra 40 items (userId 4 and 5) don't match any Switch rule, so they fall into the Fallback output. This shows you how Switch handles unexpected data in real n8n workflow automation — always add a Fallback handler when your data might include values you haven't planned for.
  11. Save your workflow
    Click Save in the top right. Your n8n HTTP Request node workflow is now complete and ready to extend with real APIs, credentials, or additional processing nodes.

Tips From Real Testing

A few things worth knowing from hands-on experience with this n8n tutorial:

The "Include Other Input Fields" bug: When using a Set node, the default setting may only pass through fields you explicitly select. Always double-check this is set to All if you need to keep the original data intact. Losing fields silently is one of the most confusing bugs for beginners in n8n workflow automation.

Switch vs IF: Use an IF node when you have two paths — true or false. Use a Switch node when you have three or more conditions. In this example, routing by userId 1, 2, and 3 is a perfect Switch use case.

Query parameters in URLs: You can add them directly in the URL field (like ?_limit=60) or use the Query Parameters section in the node settings. Both work — the settings section is cleaner when you have multiple parameters.

The JavaScript string concatenation bug: If you ever write 30 + 10 in an n8n expression and get 3010 instead of 40, it's because one value is a string. Wrap it with Number() to fix it — for example, Number($json.score) + 10. This came up during expression testing and is easy to miss.

Where to Go Next in This n8n Tutorial Series

Now that you can pull data from any API using the n8n HTTP Request node, the next steps in this n8n workflow automation series cover real-world API authentication (headers, bearer tokens), the Schedule Trigger for running workflows automatically, and connecting AI models like Gemini, Claude, and OpenAI directly into your automation pipelines.

If you want to try connecting a real API, any service with a REST API and a key works the same way — just add the key as a credential in n8n and reference it in the HTTP Request node's Authentication section. The pattern you learned here scales to any API you'll ever need.

Conclusion:

The n8n HTTP Request node is the backbone of almost every n8n workflow automation you'll build — it connects your workflows to the outside world with just a URL and a few settings. Follow the steps above and you'll have real API data flowing through your n8n tutorial projects in minutes.

If you have any questions, feel free to leave a comment below. Thank you!

Tags: n8n tutorial, n8n workflow automation, n8n HTTP request node, n8n beginner guide, n8n Switch node, n8n Merge node, n8n Code node, REST API automation

Maybe you are interested!

Copyright © 2016 QTitHow All Rights Reserved