n8n · Workflows, webhooks and APIs

9 n8n workflows for three businesses. Run every one yourself.

n8n is a workflow automation tool, like Zapier or Make. A workflow is a chain of steps that runs on its own: when a form is sent or an order comes in, it looks things up, decides, updates the right apps, and tells a person when something needs them.

I built 9 of them for three made-up businesses: a coffee roaster on Shopify, a bookkeeping firm and a recruiting agency. Each has a test form you can fill in. Everything runs here in your browser, on test events or on your own answers. Need this for your business, or hiring for n8n? Get in touch.

Workflows you can run
9
Nodes inside them
107
Test events to run them on
37
Branches, every one tested
37/37
Case study 1 · Online store and wholesale (Shopify)

Copperleaf Coffee Roasters

Copperleaf roasts about 900 pounds a week: retail bags and subscriptions through Shopify, plus 40 cafés and restaurants on wholesale. Nine people, one roaster, and nobody whose job is IT. The owner wanted three things off her plate: wholesale inquiries that sat in an inbox for days, a roast schedule copied by hand from Shopify every morning, and running out of a best-seller because nobody looked at stock until it hit zero. n8n Cloud runs the glue, so there is no server to look after.

Workflows
3
Nodes
34
Test events
14
Where
Asheville, North Carolina; ships across the US
The team, where n8n runs and the apps it connects

The sample team

  • Maya Okoye Owner and wholesale lead
  • Theo Brandt Head roaster
  • Jess Liang Packing and shipping
  • Sam Ortiz Operations (owns n8n)

Where n8n runs

n8n Cloud, Starter plan. The workload is a few hundred executions a day, so a hosted instance costs less than anyone’s time spent patching a server.

n8n FormShopifyHubSpot (free CRM)Google SheetsGoogle DriveGmailSlack

Copperleaf Coffee Roasters is a fictional business. The people, orders, prices, emails and links are samples.

Live demo

Try it: send the workflow your own answers

Fill it in as a customer would, press Send, then watch workflow 01 · Wholesale inquiry run on your answers. Nothing is sent or stored.

Wholesale coffee for your business

Tell us a little about your café, restaurant or shop. Maya, our owner, reads every one, and you will hear back by email within the hour.

Required

How the form reaches n8n, and the settings that matter.

How it is set up (4 notes for builders)
  • Field labels are the keysThe Form Trigger outputs each answer under its label, plus submittedAt and formMode. Edit Fields renames them straight away.
  • Respond When: Form Is SubmittedThe thank-you page shows at once. With Workflow Finishes, a slow HubSpot would keep the café staring at a spinner, and a failure would show them an error.
  • Test URL and production URLThe test URL works while the editor listens for a test event, and the submission appears on the canvas. The production URL works once the workflow is published, and its runs appear under Executions.
  • Ignore Bots, no attributionIgnore Bots skips link previewers and crawlers. Append n8n Attribution is off, so the page carries Copperleaf’s name only.
The workflows

Pick a workflow, pick a test event, press Execute

Each tab is one workflow. The problem and What I built are the short version; pick a test event and press Execute workflow to watch it run.

For n8n builders: the simulator follows n8n’s rules. Nodes run once per item, an If or Switch can send items down several outputs in one execution, v1 order finishes each branch before the next, a node with no input items does not run, branches meet at a Merge, and a failed production execution starts the error workflow. New to the words? Open the decoder.

01 · Lead intake

Wholesale inquiry

A café fills in the wholesale form. Within a minute it is in HubSpot with a fit score, and it has an answer that suits its size: a call with the owner, the price list, or a pointer to the subscription.

The problem

Wholesale inquiries arrived as contact-form emails in a shared inbox. Maya answered the big ones when she saw them and the rest when she had time, which could be a week. Nothing reached the CRM unless someone typed it in, and a café doing 60 pounds a week got the same wait as an office ordering four.

What I built

The website links to an n8n form. Edit Fields cleans the answers, a Code node scores the fit from volume, type of business and espresso focus, and HubSpot gets the contact, created or updated by email. A Switch then answers by tier: priority leads go to #wholesale and get a personal note from Maya with a booking link; standard ones get the price list attached from Google Drive; small ones are pointed to the café subscription. If HubSpot is down, the error output posts to Slack so someone adds the lead by hand, and the café still gets its email.

Copperleaf / Wholesale /01 · Wholesale · Inquiry intakewholesaleformPublished
Execution order
v1 (recommended)
Error workflow
None
Timezone
America/New_York
Save successful runs
Yes
Why these settings (3)
  • Timezone America/New_York, the roastery’s, with Use Workflow Timezone on in the form, so submittedAt reads in local time in HubSpot and Slack.
  • Save successful production executions is on. At a few inquiries a day the history costs nothing and answers “did this café ever get an email?”
  • No error workflow: the one external call that can fail, HubSpot, has its own error output. A failure anywhere else shows in Executions, which Sam checks each Monday.

The workflow’s nodes, drawn top to bottom so it fits any screen; on n8n’s canvas the same nodes run left to right. Scroll inside it; each node gets a green tick and its item count when the run reaches it.

  1. Trigger · n8n Form TriggerWholesale inquiry form

    Hosted by n8n at its production URL, linked from the Wholesale page. Eight fields, five required. Respond When: Form Is Submitted, so the café sees the thank-you page at once while the workflow runs.

    Parameters
    Form Title
    Wholesale coffee for your business
    Respond When
    Form Is Submitted
    Options
    Append n8n Attribution off · Ignore Bots on · Use Workflow Timezone on
  2. Edit Fields (Set)Clean up the answers

    Manual Mapping, Include Other Input Fields off. Renames the form’s labels to snake_case keys, trims and lowercases the email, and makes the weekly volume a Number, so nothing later depends on how a label is worded.

    Parameters
    email
    {{ $json.Email.trim().toLowerCase() }}
    first_name
    {{ $json['Your name'].trim().split(' ')[0] }}
    lbs_per_week (Number)
    {{ Number($json['Coffee per week (lbs)']) }}
    submitted_at
    {{ $json.submittedAt }}
  3. Code · JavaScript · Run Once for Each ItemScore the fit

    Scores 0 to 100 from pounds a week, type of business and espresso focus, and picks a tier: priority (30 lb or more, or 70 points), standard (10 lb or more) or small. The weights are in one place, so Maya can change them without touching anything else.

    Parameters and code
    // Code node, JavaScript, Mode: Run Once for Each Item.
    // $input.item is the item being processed; return one item back.
    const j = $input.item.json;
    const lbs = Number(j.lbs_per_week) || 0;
    
    // Volume carries most of the score. Wholesale pricing starts at 10 lb a week,
    // and 50 lb a week is a café that reorders every Monday.
    let score = Math.min(Math.round(lbs * 1.2), 60);
    
    const typePoints = {
      'Café or coffee shop': 25,
      'Restaurant': 15,
      'Grocery or retail': 15,
      'Office': 10,
    };
    score += typePoints[j.business_type] ?? 5;
    
    // Espresso bars reorder like clockwork and need the most training, so
    // Maya wants to meet them in person.
    if (j.focus === 'Mostly espresso') score += 15;
    score = Math.min(score, 100);
    
    const tier = lbs >= 30 || score >= 70 ? 'priority'
      : lbs >= 10 ? 'standard'
      : 'small';
    
    return { json: { ...j, fit_score: score, tier } };
  4. HubSpot · Contact › Create or UpdateAdd to HubSpot

    Matches on email, so a café that writes twice updates one contact instead of making two. Sets company, lifecycle stage Lead and two custom properties, fit score and pounds a week. On Error is Continue (using error output): if HubSpot fails, the item leaves through the Error output instead of stopping the run.

    Copperleaf HubSpot (app token)On Error: error output

    Parameters
    Email
    {{ $json.email }}
    Company Name
    {{ $json.business_name }}
    Lifecycle Stage
    Lead
    Custom Properties
    wholesale_fit_score = {{ $json.fit_score }} · lbs_per_week = {{ $json.lbs_per_week }}
    Success
    1. → Carry on either way
    ErrorHubSpot answered with an error. The item carries it and goes on.
    1. Slack · Message › SendTell #wholesale HubSpot missed it

      Names the café and the error, and says the reply email is still going out, so nobody writes to them twice. Sam adds the contact by hand.

      Copperleaf Slack (bot)

      Parameters
      Channel
      #wholesale
      Text
      HubSpot did not take {{ $('Score the fit').item.json.business_name }}: {{ $json.error.message }}
    2. → Carry on either way
  5. Merge · AppendCarry on either way

    Input 1 is the Success output, input 2 the Slack post after an error. Only one of them ever gets the item, and Append passes on whatever arrived, so the café is answered whether or not HubSpot was up.

    Parameters
    Mode
    Append
  6. Switch · RulesRoute by tier

    Reads the tier back from the Code node with $(), since the items arriving here are HubSpot’s answer or the Slack post, not the lead. Fallback Output: Extra Output, named Small.

    Parameters
    Value
    {{ $('Score the fit').item.json.tier }}
    Rules
    is equal to priority · is equal to standard
    Fallback Output
    Extra Output (Small)
    Prioritytier is equal to priority
    1. Slack · Message › SendPost to #wholesale

      Block Kit message with who, where, volume, score and their note, so Maya can decide on her phone whether to call before her email lands.

      Copperleaf Slack (bot)

      Parameters and body
      Channel
      #wholesale
      Message Type
      Blocks
      {
        "blocks": [
          { "type": "header", "text": { "type": "plain_text", "text": "Wholesale lead: {{ $('Score the fit').item.json.business_name }}" } },
          { "type": "section", "fields": [
            { "type": "mrkdwn", "text": "*Who*\n{{ $('Score the fit').item.json.contact_name }}" },
            { "type": "mrkdwn", "text": "*Where*\n{{ $('Score the fit').item.json.location }}" },
            { "type": "mrkdwn", "text": "*Volume*\n{{ $('Score the fit').item.json.lbs_per_week }} lb a week, {{ $('Score the fit').item.json.focus }}" },
            { "type": "mrkdwn", "text": "*Fit*\n{{ $('Score the fit').item.json.fit_score }}/100" }
          ] },
          { "type": "section", "text": { "type": "mrkdwn", "text": "{{ $('Score the fit').item.json.message || '_No message_' }}" } }
        ]
      }
    2. Gmail · Message › SendNote from Maya

      Sent from Maya’s own Gmail, so the reply reaches her. Plain text, one link to book a call and taste samples, and Append n8n Attribution turned off: by default the Gmail node adds a “sent automatically with n8n” line.

      Maya’s Gmail (OAuth2)

      Parameters
      To
      {{ $('Score the fit').item.json.email }}
      Subject
      Coffee for {{ $('Score the fit').item.json.business_name }}
      Email Type
      Text
      Options
      Append n8n Attribution off · Sender Name Maya Okoye
    3. End
    Standardtier is equal to standard
    1. Google Drive · File › DownloadGet the price list

      Downloads the current price list PDF by file ID into binary property data. Maya replaces the file in Drive when prices change, and the workflow never needs editing.

      Copperleaf Google (OAuth2)

      Parameters
      File
      By ID · Copperleaf Wholesale Price List 2026.pdf
      Put Output File in Field
      data
    2. Gmail · Message › SendSend the price list

      Attachments: data, the PDF from the step before. Same sender and settings as Maya’s note, and an offer of samples rather than a call.

      Maya’s Gmail (OAuth2)

      Parameters
      To
      {{ $('Score the fit').item.json.email }}
      Attachments
      data
      Options
      Append n8n Attribution off · Sender Name Maya Okoye
    3. End
    SmallFallback: nothing above matched
    1. Gmail · Message › SendSuggest the café subscription

      Under 10 pounds a week the wholesale minimum does not work for either side, so this points to the office and café subscription instead, kindly and with a discount code.

      Maya’s Gmail (OAuth2)

      Parameters
      To
      {{ $('Score the fit').item.json.email }}
      Options
      Append n8n Attribution off · Sender Name Maya Okoye
    2. End
Pick a test event
Mon Mar 2, 9:41:00 AMNot started
  1. Pick a test event above, then press Execute workflow. Each line is one node, with the time it ran and how many items it passed on; open Output to see them. Messages a person would read (Slack, email, tasks, HTTP responses) are shown as they would arrive. Waits of days are fast-forwarded.

The same workflow in n8n

Exported from this page’s data, imported into n8n 2.43 and captured from its editor. Copy it and paste it onto any n8n canvas, or download the file and import it; connect your own credentials before running it.

Download .json
01 · Wholesale · Inquiry intake on the n8n canvas: every node from the diagram above, connected left to right.
Build notes

The detail an n8n builder would check before trusting this workflow. Start with What if… for the unusual cases in plain words. Words you may not know

  • The same café submits twiceHubSpot Create or Update matches the email and updates the existing contact. The email goes out again, which is right: they asked again. If repeat inquiries ever became a nuisance, a HubSpot Get before the Switch could check when the last one was.
  • A typo in the emailThe Form Trigger’s Email field rejects anything that is not an address. A real but wrong address bounces back to Maya’s inbox, where she sees it next to the Slack post.
  • HubSpot is down or the token was revokedThe Error output fires on the first failure. #wholesale gets the café’s name and the error, and the email still goes out. A revoked token shows the same way, as a 401, on every inquiry until someone reconnects it, which the Slack posts make obvious within the hour.
  • Bots fill in the formIgnore Bots is on, which skips link previewers and crawlers. A determined spammer still gets through; the score makes junk land in the “small” tier, where the only cost is one polite email.
  • Prices changeMaya replaces the PDF in Drive, keeping the same file. The workflow downloads it fresh every time, so nobody edits n8n for a price change.
  • Gmail’s sending limitsA Google Workspace account can send about 2,000 messages a day. A few inquiries a day is nowhere near it, which is why this uses Maya’s Gmail and not a marketing tool.

n8n features in this build

  • n8n Form Trigger
  • Edit Fields (Set)
  • Code (per item)
  • HubSpot
  • Error output
  • Merge (Append)
  • Switch with fallback
  • $() item pairing
  • Google Drive binary data
  • Gmail attachments
  • Slack Blocks
  • Pinned data

Are these real businesses?

No. Copperleaf Coffee Roasters, Ledgerline Bookkeeping and Harrow & Finch Recruiting, and everyone who works there, are made up, so every workflow can be shown end to end with its real data and tried by anyone. The workflows use n8n’s real nodes, settings and behavior, checked against n8n’s documentation, so each one can be rebuilt node for node in a real instance. Where the simulator stands in for something outside n8n, like an AI model’s answer, the page says so. Nothing on this page sends a message or keeps what you type.

Who built this

I’m Nick Soderstrom, a project and operations lead who builds automations. My client automation work so far has been in GoHighLevel and Zapier (see recent contracts), and there is a GoHighLevel version of this page. These n8n cases are not client work: I built them to show how I design, test and hand off an n8n build. This page and its simulator were built by directing AI, like the projects on my AI Projects page.

n8n words in plain English (23)
n8n
A workflow automation tool, like Zapier or Make, that can also be self-hosted. It connects apps through drag-and-drop nodes and lets you drop into code where you need to.
Workflow
A set of connected nodes that runs on its own when something happens, such as “a form is sent: score it, save it in the CRM, email a reply.”
Node
One step in a workflow: a trigger, an app action like “send a Slack message”, or a logic step like If or Merge.
Trigger (the node with the lightning bolt)
The node that starts a workflow: a form, a webhook, a schedule, a new Shopify order, or another workflow failing.
Item
One record passing through the workflow, like one order or one line of an order. Most nodes run once for every item they receive.
Expression
A formula in a node’s settings, written in {{ }}, such as {{ $json.email }}. It fills in values from the item, or from an earlier node with $('Node name').
Credential
A saved login for an app, stored encrypted and chosen by name in each node, so passwords and keys never appear in the workflow itself.
Execution
One run of a workflow, with every node’s input and output saved. The Executions list shows them as Success, Error or Waiting.
Published
A published workflow listens for real events at its production URL. While building, a test URL works only while the editor is listening.
Webhook
A web address another system calls to send data, like a website posting a form. n8n’s Webhook node is a trigger with such an address.
If, Switch, Filter
If sends each item down a true or false output. Switch picks among several outputs by rules. Filter keeps the items that match and drops the rest.
Merge
Brings two or more branches back together, either one after the other or matched up by a field, like an order ID.
Split Out, Aggregate
Split Out turns a list inside one item into separate items, like an order into its lines. Aggregate gathers items back into one.
Code node
A node that runs a short JavaScript program on the items, for logic no ready-made node covers.
HTTP Request
A node that calls any web API directly, for apps or endpoints n8n has no ready-made node for. It can still use a saved credential.
Wait
Pauses an execution for a set time, or until a link is opened or a form is sent. Long waits are saved to the database and resumed later.
Error workflow, Error Trigger
A workflow that starts when another one fails, usually to alert someone with a link to the failed execution.
Error output, Retry On Fail
Node settings for failure: try again a few times, or send the failed item out of a separate Error output so the rest of the workflow carries on.
Sub-workflow
A workflow started by another one through the Execute Sub-workflow node, like a function a program calls.
Execution order v1
The rule n8n uses when a workflow branches: finish one branch before starting the next, top to bottom on the canvas.
Pinned data
Sample input saved on a node, so the workflow can be tested again and again without a real event.
Information Extractor, chat model
An AI node that pulls the fields you describe out of free text, like years of experience from a résumé, using a language model such as OpenAI’s, attached as a sub-node.
Self-hosted
Running n8n on your own server instead of n8n Cloud, for control over where data goes.
Reliability

Built for the day something fails

An automation that works in a demo is easy. One that a business can forget about has to survive slow APIs, duplicate events, revoked logins and empty days without losing anything or crying wolf. These habits are in every case study. In plain words: nothing fails silently, nothing happens twice, secrets stay locked away, and the workflows stay quiet unless a person needs to act.

Troubleshooting

What I check first when I inherit an n8n instance

Most fragile n8n setups fail in the same few ways. This is the order I look in, and what I do about each.

  1. No error workflowThe most common gap. Failures are red rows in a list nobody opens. I add one error workflow for the instance and set it on every workflow before changing anything else.
  2. Credentials tied to one personOAuth connections made from someone’s own Google or Slack account stop working the day they leave. I move them to service accounts or shared automation users, and name every credential after its company, app and auth type.
  3. Webhooks with no authenticationA production URL anyone can post to, often found in a site’s front-end code. Header auth with a server-side secret, or the app trigger’s own signature check.
  4. Secrets in plain sightAPI keys pasted into HTTP Request headers or Code nodes, which then show in every execution and every export. Moved into credentials, then rotated, since they have been visible.
  5. Test URLs in productionA site pointing at /webhook-test/, which only answers while someone has the editor open. It works in the demo and fails at night.
  6. Old execution orderWorkflows from before n8n 1.0 can still run on the legacy order, where a Merge after an If can run both branches. I check the setting and retest those workflows before switching them to v1.
  7. Executions piling upEvery successful run saved forever, with customer data in it, and a database that keeps growing. I set what is saved per workflow and how long executions are kept.
  8. Code doing a node’s jobHundreds of lines in a Code node to call an API or reshape data that Split Out, Aggregate or HTTP Request already handle, which the next person cannot read. Code stays for logic that is genuinely the business’s own.
How I work

From a brief to a workflow the team trusts

  1. Scope

    What starts it, what done looks like, who hears about what, and what must never happen twice. Written down before a node is placed.

  2. Map the data

    The trigger’s real payload, saved from a test event, and the fields each app needs. Credentials created with the least access that works.

  3. Build on pinned data

    Real test events pinned on the trigger, so every node can be run and rerun without sending anything. One job per workflow, named so it sorts.

  4. Break it on purpose

    Wrong credentials, a slow API, a duplicate event, an empty result: each test event in this page’s simulators is one I would run against a staging copy.

  5. Publish and hand off

    Published at a quiet hour, the site switched to the production URL, the error workflow set. Then a short recorded walkthrough and a one-page how-to: what it does, what to change, what never to touch.

  6. Watch it

    The Executions list filtered to Error in the first week, then monthly, and the error workflow’s alerts read as they come. Fixes are retried from the failed node, so nothing runs twice.

Naming, so the next person can find things

Workflows
01 · Onboarding · New client in a folder per area, so they sort in the order they run
Nodes
Look up the client, not Google Sheets1: what it does, since $() expressions use the name
Credentials
Ledgerline Google (OAuth2): company, app and auth type
Tags
client-facing, schedule: what the error workflow and a reviewer need to know

Hiring for n8n, or need it built?

I design, build, fix and document automations: the workflows, the error handling around them, and the handoff so a team can run them. If you’re hiring for an automation role or need this for your business, I’d like to hear about it.