Choosing an Automation Platform — Volume B: Connectivity

Choosing an Automation Platform — Volume B: Connectivity

The app catalogs, connections and credentials, triggers, webhooks and raw HTTP, and what to do when the catalog falls short.

A Signal Through field guide. Independent and vendor-neutral; not affiliated with n8n GmbH, Celonis (Make), or Zapier Inc. Approximately 22496 words.

In this volume:


The App Catalogs

Every automation platform sells itself on a number. Zapier's marketing leads with a directory of 8,000-plus apps (its developer platform cites a higher figure still). Make's banner count sits in the low thousands and recently crossed 3,000. n8n's own count is more modest — it advertises 400-plus core integrations — though broader tallies that fold in every app entry run past 1,000, and higher again once you add community-built nodes. These numbers are real as snapshots — each creeps upward every year — but they are also the single most misleading comparison in the entire category, because each platform counts something different, and because a directory entry tells you nothing about whether the connector behind it can actually do the job you need.

This chapter does two things. First, it explains what a prebuilt integration actually is on each platform — a Zapier app, a Make app with its modules, an n8n node — so that when you browse a catalog you understand what you are looking at. Second, it teaches you a diligence routine: a short, repeatable checklist for verifying that the tools you personally depend on are covered well, not just covered nominally. The gap between those two words is where automation projects quietly die three weeks in.

One scoping note before we start. When the catalog genuinely falls short, every platform gives you escape hatches — raw HTTP calls, code steps, and building your own connector. Those are covered in Chapter 9 (Webhooks and Raw HTTP) and Chapter 10 (When the Catalog Falls Short: Custom Connectors and Code Steps). Here we stay inside the catalog itself, including the community-built extensions that stretch it without requiring you to build anything.

What a Prebuilt Integration Actually Is

Strip away the branding and a prebuilt integration on any platform is the same thing: a packaged wrapper around another product's API. An API — application programming interface — is the machine-facing doorway a software product exposes so that other software can read and change its data. Every SaaS product you use — SaaS meaning software-as-a-service, the subscription tools your business runs in a browser, like your CRM (customer relationship management tool — the shared customer database your sales team lives in), your email tool, your accounting software — has one, and in principle you could talk to it directly with code. A prebuilt integration saves you from that. Someone has already done the work of handling the product's login handshake, learning its endpoints (the specific URLs you call to create a contact, fetch an invoice, and so on), and translating all of it into friendly dropdown menus and form fields inside the automation editor.

So when you drop "Salesforce" into a workflow, you are not connecting to Salesforce in some abstract sense. You are using a specific piece of wrapper software, written and maintained by a specific party — sometimes the platform, sometimes the app's own vendor, sometimes a third party — that exposes a specific, finite list of things it knows how to do. That list is the integration's real identity. The logo is decoration.

Each platform packages this wrapper differently, and the differences matter when you read the catalogs.

On Zapier: apps, with triggers, actions, and searches

Zapier calls each integration an app. Inside an app, capabilities come in three flavors:

That is the whole vocabulary. When you evaluate a Zapier app, you are evaluating its list of triggers, actions, and searches — nothing more. Zapier's public directory shows this list on each app's profile page, and you can read it without creating an account. The distinction between trigger types (some fire instantly, some check on a schedule) matters enormously and is the subject of Chapter 8 (Triggers: How Workflows Start).

Zapier also ships a set of built-in utility apps — Formatter, Filter, Paths, Delay, Webhooks by Zapier (a webhook is a direct machine-to-machine message one system pushes to another over the web — Chapter 9's whole subject), Code by Zapier, and others. These appear in the same picker as real integrations, but unlike a Salesforce or Gmail app they are not wrappers around a specific outside product — they are workflow plumbing. (A couple of them, notably Webhooks and Code, can reach the open web, but they are generic tools, not connectors to a named service.) Do not count them when you assess catalog coverage, and do not be alarmed that other platforms "lack" them — Make and n8n ship the same plumbing under different names, as you saw in Chapter 4 (The Rosetta Stone, the Capability Map, and How to Decide).

On Make: apps, with modules

Make also calls each integration an app, but the units inside are modules — the round icons you drag onto a scenario canvas (a scenario is Make's word for a workflow). Modules come in several types:

A Make app is therefore a bundle of modules, and Make's public app directory lists every module an app offers, grouped by type. This is worth internalizing: when Make says it supports an app, the honest question is "with which modules?" An app with one polling trigger and two actions is in the catalog just as much as an app with forty modules — the directory entry looks identical at a glance.

Make apps also frequently include a module called something like "Make an API Call" — a partially-wired escape hatch that reuses the app's saved login to hit any endpoint of the underlying API, even ones no module covers. It occupies a middle ground between prebuilt convenience and the raw HTTP work of Chapter 9, and its presence is a genuine point in an app's favor.

On n8n: nodes, with resources and operations

n8n's unit is the node — a box on the workflow canvas. Nodes split into trigger nodes, which start workflows, and regular nodes, which do work mid-flow. Where Zapier and Make enumerate each capability as a separately named trigger, action, or module on the app's page, an n8n node typically packs many capabilities behind two dropdowns inside a single node: Resource (which kind of object — contact, deal, message) and Operation (what to do to it — create, get, get many, update, delete).

This packaging difference has a direct consequence for reading catalogs: one n8n node can equal a dozen Zapier actions. The Notion node, for instance, is one directory entry, but its resource-and-operation grid covers databases, pages, blocks, and users, each with several operations. Raw entry counts therefore systematically understate n8n's per-app depth — though on sheer breadth, the catalog really is the smallest of the three.

n8n's catalog has one more wrinkle: some directory listings are credential-only integrations. n8n lets you save login details for a service and then use them inside the generic HTTP Request node, even when no dedicated node exists. It is honest — the authentication is genuinely prebuilt — but the listing is a doorway to hand-rolled API calls, not a menu of ready-made operations. Check whether a listing is a full node or a credential-only entry before you count it as coverage.

Tip: The fastest way to understand any platform's integration model is to open one app's directory page and read the capability list top to bottom. Five minutes with the Zapier, Make, and n8n pages for the same app — pick one you know well — will teach you more about the three catalogs than any marketing comparison.

Reading the Numbers Honestly

Now the billboard numbers. Here is what each one actually measures:

Zapier Make n8n
Catalog unit App App Node
Rough directory size 8,000+ apps 3,000+ apps 400+ core nodes; 1,000+ by broader tallies
What one entry contains A list of triggers, actions, searches A list of modules by type Resources and operations inside one node (or a credential-only entry)
Typical builder of the entry The app's own vendor, via Zapier's developer platform Make, the vendor, or a partner n8n's team, or the community
Generic API fallback Webhooks by Zapier (separate app) HTTP app, plus per-app "Make an API Call" modules HTTP Request node, plus credential-only integrations

Three honest observations follow.

The counts are not commensurable

Zapier counts apps, and its number is genuinely the largest — no asterisk needed on breadth. But an "app" is a container of unstated size on every platform, so the headline figures are a comparison of container counts, not capability counts. Nobody publishes a total-actions-across-the-catalog figure, and if they did it would drift weekly. Treat the big numbers as answering exactly one question: how likely is it that an obscure tool has at least some presence here? On that question, Zapier's long tail is a real advantage. If you run a niche vertical SaaS product for dental practices or scaffolding rental, the odds it has a Zapier app and nothing else are meaningfully high, because vendors build for Zapier first when they build for anything at all.

Breadth and depth trade against each other

The market has sorted itself into a rough pattern you can verify yourself with the diligence routine below:

None of this is a verdict. A wide-shallow catalog is exactly right if your stack is twenty ordinary SaaS tools and your needs per tool are simple. A narrow-deep catalog is exactly right if your stack is eight tools you push hard. The point of this chapter is to move you from arguing about the numbers to checking your own case.

Who builds the connector shapes its quality

On Zapier, integrations are overwhelmingly built and maintained by the app vendors themselves through Zapier's developer platform. That is why the catalog is huge — thousands of vendors each doing their own small amount of work — and also why quality varies: the connector is only as good as that vendor's commitment. On Make and n8n, a larger share of the catalog is built by the platform itself or by a small circle of partners and community contributors, which produces more uniform depth but slower coverage of new tools. When a connector misbehaves, knowing who maintains it tells you where to file the complaint — and whether anyone is listening.

Watch out: A directory entry is not a commitment. Vendors deprecate their own connectors, APIs change underneath them, and an app that worked when you evaluated it can lose a trigger in an update. For any integration that will carry a business-critical workflow, check when it was last updated and whether the vendor still advertises it — a connector page that has not changed in years, wrapping an API that has, is a slow-motion outage. Chapter 27 (Monitoring, History, and Alerting) covers how to find out quickly when it finally breaks.

The Operator's Diligence Routine

Here is the routine to run before you commit to a platform — ideally before you even open a trial account. It takes an hour for a typical small-business stack and it is the highest-leverage hour in the whole evaluation. All three directories are public and searchable without an account, which makes this a pure reading exercise.

Step 1: Inventory the tools you actually use

Write a flat list of every product your workflows will touch. Not categories — products, with editions. "Accounting" is not an entry; "QuickBooks Online" is. Editions matter because connectors frequently support one edition of a product and not another: the online edition but not the desktop one, the marketing product but not the transactional sibling, the current API but not the legacy tier your ten-year-old account still sits on.

Then mark each entry with the direction of data flow you need: does this tool need to start workflows (trigger), receive data (action), or answer lookups (search)? A calendar you only ever write events into needs actions; a form tool that only ever starts things needs a trigger. This ten-minute annotation is what turns Step 3 from vague browsing into a checklist.

Step 2: Verify coverage — the exact product, not the brand

Search each platform's directory for every item on your list. You are checking three things:

  1. The app exists at all. Usually it does on Zapier; often on Make; less often, for long-tail tools, on n8n — where you should also check whether a community node exists (more below) or whether a credential-only entry covers it.
  2. It is the right product. Big brands ship many products with confusingly similar names, and directories list them as separate apps. Google alone contributes a dozen entries; pick the wrong one and nothing you need will be there. Match on the product name your team actually logs into.
  3. It is the right edition and region. Accounting and payroll tools are the classic trap — products that exist in country-specific editions or online/desktop splits where the connector covers only one branch of the family.

Watch out: The most expensive version of this mistake is discovering the edition mismatch after migration. A team that verified "our accounting tool is supported," signed an annual plan, and then learned the connector only spoke to the cloud edition while their data lived on the desktop one has not automated anything — it has bought a subscription and inherited a data-migration project. Verify against the login screen your team uses, not the brand name.

Step 3: Read the trigger and action list before committing

This is the heart of the routine. For each tool that passed Step 2, open its directory page and read the full capability list against your Step 1 annotations. Specifically:

Do this for your three or four critical tools with full attention, and skim the rest. The critical tools are the ones where a capability gap kills the project; the rest can usually be patched with the techniques in Chapters 9 and 10.

Step 4: Spot the shallow connector

Shallow connectors — technically present, practically useless — cluster around recognizable warning signs:

Warning sign What it usually means
Two or three actions, no triggers The vendor built the minimum to claim a directory listing; the app can be written to but can never start a workflow
Triggers but no search steps Fine for fire-and-forget notifications, painful for anything that must look up existing records
Only polling triggers on an app that is obviously real-time (chat, telephony) The integration predates or ignores the app's push notifications; expect delays
A "beta" or "by invitation" label that has persisted for a long time Development stalled; treat as abandoned until proven otherwise
Capability list that does not mention the app's newest flagship features Maintenance lags the product; your workflows will be limited to what the app did years ago
On n8n: a credential-only listing Authentication is prebuilt but every operation is a hand-built HTTP call — real coverage, different effort level

A shallow connector is not automatically a dealbreaker. If the two actions it offers are the two actions you need, it is a perfect connector for you. The routine exists precisely so you make that judgment from the capability list instead of from the logo grid.

Step 5: Note the commercial gates

Catalog access is not always uniform within a platform. Zapier has historically designated some high-value integrations as premium, available only on paid tiers; platforms also gate features of the catalog — such as how frequently polling triggers check for new data — by plan. Do not memorize the current rules, which drift; just add a line to your diligence notes for each critical tool: "available on the plan we would actually buy?" Chapter 31 (Unit Economics) treats the pricing side properly.

Tip: Keep the finished inventory as a living document — one row per tool, columns for each platform, cells recording trigger/action/search coverage and any gates. It is twenty minutes of formatting on top of work you already did, it becomes the evidence base for the decision framework in Chapter 35, and it is the first thing you will reach for when a teammate proposes adding a new tool to the stack.

Extending the Catalog Without Building

Every catalog has edges, and each platform has a sanctioned way to push them outward without writing a connector yourself. These extenders belong in your diligence routine, because a tool missing from the main directory may be sitting in one of them.

n8n: community nodes

n8n's headline extender is the community node: a connector written by someone outside the n8n team and published as an open-source package that any self-hosted n8n instance can install. On a self-hosted instance, an administrator installs them from inside the product — look under Settings > Community Nodes — by naming the package. The public npm registry (the package repository the JavaScript world runs on) hosts hundreds of them, covering tools the core catalog has not reached and adding deeper alternatives to nodes it has. n8n's own integration directory lists many community nodes alongside official ones, labeled as such, and n8n has been progressively opening its cloud product to a vetted subset of them, so self-hosting is no longer strictly required for the most popular ones.

Two cautions. First, a community node is third-party code running inside your automation platform with access to your credentials — treat installing one like hiring a subcontractor, and prefer nodes that are widely used, recently maintained, or carry n8n's verification label. Second, community nodes vary in quality exactly the way long-tail Zapier apps do; run the same Step 3 capability read on a community node that you would on anything else.

Watch out: On self-hosted n8n, a community node runs with the same privileges as the platform itself. A malicious or merely sloppy package can read any credential your instance holds. Restrict who can install them, review what you install, and revisit the list occasionally — the security posture of your automation platform is only as strong as its least-trusted node. Chapter 32 (Hosting, Security, and Compliance) picks this thread up in full.

Make: partner-built and shared custom apps

Make's catalog is extended mainly by partner- and vendor-built apps that go through Make's review process and land in the ordinary directory — as a user you mostly experience this as the catalog simply growing. Below that, Make supports custom apps that a developer builds once and shares with specific teams or clients by invitation, without public listing. If you work with an agency or a SaaS vendor that says "we have a Make app," it may be one of these invited apps rather than a directory entry — functionally identical to use, just not discoverable by search. Ask for the invitation link and then run the same capability read.

Zapier: private and by-invitation apps

Zapier's directory is extended the same way at the margin: developers can build an integration on Zapier's platform and share it privately by invite link without publishing it publicly. Niche vendors sometimes maintain invite-only Zapier apps for their customers, and agencies build private apps for clients. If a tool you need is missing from the public directory, it costs one email to the vendor to ask whether a private Zapier or Make app exists — a surprisingly common happy ending.

What all three extenders have in common: someone else already did the building. The moment the answer to a gap is "we could write our own node/app/integration," you have left this chapter's territory and entered Chapter 10 (When the Catalog Falls Short: Custom Connectors and Code Steps) — a genuinely viable path, but one with real construction and maintenance costs that deserve their own treatment. And for one-off gaps too small to justify a connector at all, the raw HTTP techniques of Chapter 9 are usually the right tool.

What the Catalog Tells You About the Decision

After the diligence hour, you will hold one of three results, and each maps to a clear posture:

Everything critical is covered deeply on all three platforms. Common for mainstream stacks. The catalog stops being a deciding factor, and your decision shifts to the criteria of later volumes — data handling (Volume C), pricing model (Chapter 31), hosting (Chapter 32), and the framework of Chapter 35.

Coverage diverges. One platform covers your critical tools deeply, another shallowly or not at all. This is the catalog earning its place as a first-class decision criterion. Weight the critical tools heavily and the long tail lightly: a missing connector for a peripheral tool is a Chapter 9 workaround, but a shallow connector for the system of record at the center of your business — the tool holding the authoritative copy of your data — is a standing tax on everything you build.

A critical tool is covered nowhere. Rarer than the marketing wars imply, and not a dead end — it means the platform's extensibility becomes your real evaluation axis. How pleasant is raw HTTP on each platform? How mature is the custom-connector path? Those questions belong to Chapters 9 and 10, and platforms rank differently on them than on catalog size — this is where n8n in particular tends to recover ground the directory numbers cost it.

One closing habit: re-run the abbreviated routine whenever your stack changes. Catalogs move — apps deepen, stall, and occasionally vanish — and the tool you adopt next quarter deserves the same hour of reading this quarter's tools got. The operators who get burned by app catalogs are almost never the ones who chose the "wrong" platform; they are the ones who read a logo grid, saw their brands represented, and never opened a single capability list. You now know better, and it costs an hour.


Connections and Credentials

Every workflow you build will, at some point, need to act on your behalf inside another product: read an email, append a spreadsheet row, post a chat message. Before any of that can happen, the automation platform has to prove to that other product that it is allowed to. That proof — stored, named, and reusable — is what all three platforms call a connection (n8n calls its version a credential; the idea is identical). A connection is a saved, authenticated link between your automation platform and one account in one app. Create it once, reuse it across every workflow that touches that app.

This chapter explains the two authentication styles you will meet everywhere — API keys and OAuth — walks the credential store of each platform by connecting the same three everyday apps (an email service, a spreadsheet, and a team chat tool) on all three, and then covers the unglamorous parts that separate a hobby build from a dependable one: what to do when a connection breaks, why tokens expire, and the hygiene habits that keep a credential mess from becoming a security incident. Hand-writing authentication headers for do-it-yourself API calls is Chapter 9 (Webhooks and Raw HTTP) territory; organization-wide rules about who may create and share credentials belong to Chapter 29 (Teams, Governance, and Change Management). Here we stay at the level every builder needs on day one.

The Two Ways Software Proves Who It Is

When you log into a website, you type a username and password. Software talking to software almost never does that. Instead, the industry settled on two main patterns, and nearly every connection you create will be one of them.

API keys: a password for software

An API key is a long random string of letters and digits — something shaped like ak_x7Q2m..., often dozens of characters long — that a service issues to you so that programs can reach its API (the software-facing doorway an app exposes) and act on your account. Think of it as a password designed for software: no human is meant to memorize it, and it is usually pasted exactly once, into the platform that will use it.

You typically obtain an API key by logging into the service's website yourself and finding a developer or integrations area — often somewhere like Settings > API or a page labeled "API tokens" or "Developer settings." The service generates the key, shows it to you (often only once), and from then on any request accompanied by that key is treated as you.

Three properties of API keys matter for how you handle them:

When a platform asks you for an API key during connection setup, it stores the key encrypted in its credential vault and attaches it to outgoing requests for you. You never handle it again — which is exactly the point.

OAuth: the "Sign in with Google" grant

OAuth (usually OAuth 2.0, the current version) is the protocol behind every "Sign in with Google" and "Allow this app to access your account" screen you have ever clicked through. Instead of you copying a secret between two websites, the two services talk to each other directly, and your only job is to say yes.

The flow, in plain English:

  1. In your automation platform, you click something like "Connect a new account."
  2. A pop-up window opens on the other service's own website — Google's, Slack's, Microsoft's. You log in there if you aren't already. Your password is typed only into the real service, never into the automation platform.
  3. The service shows a consent screen: "This application would like to: read your email, send email on your behalf…" — a list of the specific permissions being requested.
  4. You approve. The service hands the automation platform a pair of tokens: an access token (a short-lived pass that authorizes actual requests, often valid for an hour or so) and a refresh token (a longer-lived secret the platform uses to fetch fresh access tokens quietly in the background, without bothering you).

From your seat, the result feels the same as an API key — a saved connection you can pick from a dropdown. Under the hood it is meaningfully better: your password never left the real service, the grant is scoped to specific permissions, and you can revoke it at any time from the service's side (Google, for example, lists every app you've authorized under your account's security settings, with a revoke button for each).

That service-side revoke list is also your audit trail: once in a while, open the "third-party access" or "connected apps" page of your Google, Microsoft, and Slack accounts and remove anything you no longer recognize. Automation platforms will appear there by name.

Scopes: what a connection actually receives

The permissions listed on an OAuth consent screen are called scopes. A scope is a named slice of capability — read spreadsheets, send email, post messages — and the token the platform receives is good for those slices and nothing else.

This matters more than most beginners expect, in both directions:

n8n, being the most hands-on of the three, exposes scopes more than the others: its generic OAuth credential asks you to type the scope list yourself, and when you bring your own OAuth client (more on that below) you control what it requests. Zapier and Make decide scopes for you. Neither approach is wrong; they are different points on the convenience–control dial you will recognize from Chapter 2 (Meet the Three Product Families).

Other patterns you will occasionally meet

A few connection types fall outside the two big patterns. Basic auth is simply a username and password sent with each request — older or self-hosted tools still use it. A personal access token is an API key by another name, issued per-user by tools like GitHub or Notion. A service account is a Google-ecosystem concept: a robot identity with its own email-like address and a downloadable key file, useful when no human should be in the loop at all. And some enterprise tools use short-lived certificates or signed requests that the platform's connector handles invisibly. In every case the platform's connection dialog tells you exactly which pieces it needs; your job is only to know where to find them in the other service. When you graduate to calling APIs the catalog doesn't cover, you will handle these raw materials yourself — that is Chapter 9's subject.

Three Credential Stores, One Idea

All three platforms separate the workflow (the logic) from the connection (the authenticated link), and each gives you a central place to see every connection you have made. Learning where that place is — before you have a 2 a.m. outage — is the single most useful piece of orientation in this chapter.

Zapier Make n8n
What it's called App connection Connection Credential
Where it lives The App Connections page in the left-hand navigation The Connections page in the team's left-hand menu The Credentials section of the left navigation
Belongs to Your Zapier account; shareable with teammates on team-oriented plans The Make team (workspace); teammates in that team can use it The creating user; shareable with projects or users on paid tiers
Typical creation moment Inline, while building a Zap step Inline, from a module's connection field Inline from a node, or ahead of time from the Credentials tab
Reconnect / repair Select the app, then the connection, then reconnect Open the connection and reauthorize or verify it Open the credential and re-run the sign-in

A few texture notes the table can't carry:

Zapier treats connections as a mostly invisible convenience. You will usually create one mid-build: add a Gmail step, and Zapier prompts "Connect a new account" right there in the step editor. The central list — the App Connections page in the left-hand navigation — exists chiefly for maintenance: seeing every connected account, testing whether each still works, renaming, and disconnecting. Each connection row has a test option that makes a live call to verify the credentials still function; make friends with it.

Make scopes connections to the team (Make's word for a shared workspace). Any scenario in the team can use any of the team's connections, which is convenient and also exactly why naming discipline matters — "Google Sheets connection 3" tells a teammate nothing. The Connections page lists every connection with its app, creation date, and a verify action that live-tests it.

n8n is the most explicit of the three, in keeping with its developer-tool personality (Chapter 2). Credentials are first-class objects with their own editor: you can open one, see exactly which fields it stores, and — for many apps — see and adjust the scopes requested. Two n8n-specific facts to internalize early. First, credentials are encrypted at rest (scrambled as stored on disk, unreadable without a key) using an encryption key; on n8n Cloud this is managed for you, but if you self-host, that key lives in your instance's configuration, and losing it means every stored credential becomes unreadable. Second, on a self-hosted instance there is no vendor standing between you and OAuth providers, which changes the setup work for Google-style connections — more on that in a moment.

Watch out (self-hosters): Back up your n8n encryption key the day you install, and store it somewhere other than the server itself. A restored database without the matching key is a museum of credentials you can see but never use again.

Tip: On every platform, rename connections the moment you create them, using a convention like app – account – purpose: "Gmail – ops@yourco.com – order notifications." Six months from now, the difference between that and "Gmail account 2" is an hour of detective work.

The Same Three Apps, Three Times

Nothing demystifies credential stores like connecting real apps. We'll use the same trio you met in Chapter 5 (Hands On): Gmail for email, Google Sheets for spreadsheets, and Slack for chat. Between them they cover the three situations you will meet most often: a heavyweight OAuth provider with strict rules (Google's email service), a second app from the same provider (which teaches you how per-app scoping works), and an OAuth app with a bot-versus-human wrinkle (Slack).

Email: connecting Gmail

On Zapier, add any Gmail trigger or action to a Zap and choose to connect a new account. The Google sign-in pop-up opens; you pick the account, review the consent screen — note how many scopes a general email connector needs — and approve. Done. Zapier is a Google-verified app, so the consent flow is the polished, familiar one.

On Make, the experience is nearly identical for business accounts: in a Gmail module, create a new connection, sign in, consent. One wrinkle worth knowing: Google gates its most sensitive scopes (full mailbox access) behind an app-verification program, and the polished flow is aimed at Google Workspace (business) accounts. For personal @gmail.com accounts, Make's documented path is the longer road: create your own OAuth client — your own registered app identity — in Google's developer console and enter its details in the connection dialog's advanced settings. Follow whichever path the dialog recommends for your account type; this is an area where Google's policy, not the platform, sets the rules.

On n8n, the path depends on where n8n is running. On n8n Cloud, Google connections work Zapier-style: click to connect, sign in, consent, because n8n operates a verified OAuth app on your behalf. On a self-hosted instance, you are the OAuth app. That means the same detour Make requires for personal accounts, done once: in Google's developer console, create a project, enable the Gmail API, create an OAuth client, and paste the resulting client ID and client secret (the two identifiers that tell Google which application is asking) into n8n's Gmail credential form, along with copying n8n's redirect URL (the address Google sends the browser back to after consent) into the Google side. It is fifteen minutes of form-filling the first time and two minutes every time after, and it buys you something the hosted platforms can't offer: the consent screen shows your app's name, and no third party ever holds your tokens.

Watch out: Google treats OAuth apps that are still in "testing" status as temporary — refresh tokens for unpublished apps expire after about a week, at which point the Google connections built on them silently die and need reconnecting. If your Google credentials keep breaking on a weekly rhythm — on self-hosted n8n, or on Make with a custom client — this is almost certainly why: publish the OAuth app (move it out of testing status in the Google console) and the tokens become long-lived.

Spreadsheet: connecting Google Sheets

Here the lesson is about scopes and reuse. Sheets is a different Google product with different scopes, so on all three platforms it is a separate connection from Gmail — even for the same Google account. Expect a second consent screen listing spreadsheet permissions instead of mail ones.

On Zapier and Make, the flow repeats exactly: new connection from within a Sheets step or module, sign in, consent. Since you are likely already signed into Google in the browser, the whole thing takes ten seconds — which is precisely when mistakes happen.

Watch out: The OAuth pop-up connects whichever Google account your browser is currently signed into, and if you're signed into several it preselects one. Connecting your personal account when you meant the work one is the single most common credential mistake in these platforms, and you often won't notice until a workflow writes rows into a spreadsheet nobody else can see. Always read the account chooser.

On self-hosted n8n, the good news: the Google console detour amortizes. The OAuth client you created for Gmail can serve Sheets too — enable the Sheets API in the same Google project, and the Sheets credential in n8n can reuse the same client ID and secret. You still consent separately, because scopes are granted per credential.

Chat: connecting Slack

Slack introduces a distinction the first two apps hid: who is the workflow acting as? Slack has two kinds of identity for automation — acting as you (messages appear from your name) and acting as a bot (messages appear from an app identity you name and give an icon). All three platforms surface this choice somewhere.

On Zapier, connecting Slack is a standard OAuth consent against your workspace. When you build a "send message" action, the step offers a toggle-style choice about whether the message is sent as you or as a bot; sending as a bot is the right default for anything a team relies on, because it survives you personally leaving the workspace.

On Make, the connection dialog itself asks which flavor you are creating — a user-style connection or a bot-style one — before the OAuth consent runs. If in doubt, create the bot flavor for posting messages and a user flavor only when a workflow genuinely must act as a specific human (for example, updating your own status).

On n8n, n8n Cloud offers a click-to-connect OAuth shortcut for posting to Slack, but self-hosted instances — and some setups anywhere, notably listening for Slack events, which is Chapter 8's territory — run through creating a Slack app in Slack's own developer console, Slack's equivalent of the Google detour. You create an app in your workspace, grant it bot token scopes (such as the ability to post to channels) on the app's OAuth & Permissions page, install the app to the workspace, and paste the resulting bot token into the n8n credential — or wire up the full OAuth flow with client ID and secret. Again: more steps, more control, and the app appears in Slack under a name and icon you chose.

One universal Slack gotcha, independent of platform: a bot can only post into channels it has been invited to. If your workflow's Slack step fails with a "not in channel" style error while the connection tests fine, the credential is healthy — someone just needs to /invite the bot into the target channel.

When Connections Break

Connections fail. Not often, and rarely at a convenient time, but a builder who understands why they fail can fix in two minutes what otherwise burns an afternoon.

Why tokens expire

API keys mostly break for one reason: revocation. Someone rotated the key on the service side (deliberately or via a "regenerate" button they didn't realize was destructive), disabled the account, or the key's owner left the company and their account was deactivated. The platform is still faithfully sending the old key; the service now rejects it.

OAuth connections have more moving parts, so more ways to break:

What a broken connection looks like

You will rarely see the words "your token expired." Instead you'll see the downstream symptoms: workflow runs failing with authorization-flavored errors (HTTP 401 Unauthorized or 403 Forbidden if the platform surfaces status codes — the numeric language of "who are you?" and "you can't do that"), a trigger that simply stops producing new runs, or a platform email telling you an app needs your attention. The platforms differ in how loudly they announce it: Zapier and Make actively monitor connection health, mark the affected connection in their central lists, and usually email the owner; n8n is more passive, surfacing the failure in the affected workflow's execution log when a run hits the broken credential (Chapter 27 covers monitoring and alerting properly).

The diagnostic move is always the same: go to the credential store, find the connection, and run its test/verify action. If the test fails, it is a credentials problem; reconnect. If the test passes but the workflow still fails, the credential is fine and the problem is permissions on the specific resource or something in the workflow itself — Chapter 28 (Diagnosing Failures) picks up that thread.

Reconnecting, platform by platform

Reconnecting is deliberately undramatic on all three:

Two follow-ups turn a reconnect from a patch into a fix. First, re-run or replay what was missed: reconnecting restores the pipe but does not automatically process the events that failed while it was down — each platform has a replay/retry mechanism for failed runs (Chapter 19, Error Handling by Design, and Chapter 27 cover these). Second, ask why it broke: if the answer is "Dana changed her password" or "that was Miguel's login and he left," you don't have a token problem, you have a hygiene problem — which brings us to the last section.

Tip: When reconnecting an OAuth app, do it in a browser signed into the correct account — ideally a private/incognito window where you sign in deliberately. Reconnecting while signed into the wrong Google or Microsoft account replaces a broken-but-correct connection with a working-but-wrong one, which is strictly worse.

Credential Hygiene

Everything above is mechanics. What follows is judgment — the small set of habits that determine whether your credential store ages into a tidy toolbox or a junk drawer with live wires in it.

Least privilege: grant what the workflow needs, not what's easy

Least privilege is the security principle that any identity should hold the minimum power required to do its job. Applied here:

Never connect personal logins

This is the hygiene rule with the highest payoff per unit of effort: workflows that a team depends on should never run on a person's individual login. The reasons compound:

The remedy is a dedicated automation account (sometimes called a service or bot account): a real account in each critical service — automation@yourco.com, ops-bot — created for machines, licensed if the service requires it, granted access only to the resources workflows genuinely need, and with credentials held by the team rather than an individual. Connect that to your automation platform. Messages come from a name that signals automation; offboarding a human breaks nothing; and the account's access list doubles as documentation of what your automations can touch.

Watch out: A dedicated automation account with a full administrator role is least privilege theater — you've decoupled from human departures but kept the unlimited blast radius. Give the automation account member-level access plus specific grants, not the admin role, unless a workflow provably requires it.

Personal versus shared credentials

Within the platforms themselves, there is a second sharing question: who on your automation team can use a connection once it exists?

A workable rule of thumb across all three: shared workflows deserve shared credentials backed by an automation account; personal experiments can use personal connections, clearly named as such. The moment a personal experiment becomes something a colleague depends on, migrating its connections is part of promoting it — not optional polish.

Small habits that pay rent

These habits are the individual-scale version of governance. When you have multiple builders, environments, and an auditor asking questions, the same concerns become policy — approved connection lists, ownership registers, credential reviews on offboarding — and that organizational layer is covered in Chapter 29 (Teams, Governance, and Change Management), with the security and compliance backdrop in Chapter 32 (Hosting, Security, and Compliance).

What You Can Now Do

You can read any connection dialog and know what it is really asking for; you can tell an API key from an OAuth grant and explain why the pop-up wants the permissions it lists; you can find, test, rename, and repair connections in all three credential stores; and you know the two habits — least privilege and no personal logins — that prevent most credential grief before it starts. That is the full toolkit for the catalog-connector world of Chapter 6. When you step outside the catalog and start making raw HTTP calls of your own, you will handle these same secrets by hand — headers, tokens, and all — and that is exactly where Chapter 9 (Webhooks and Raw HTTP) begins.


Triggers: How Workflows Start

Every workflow, on every platform, begins with a trigger: the event that tells the platform "start a run now, and here is the piece of data to start it with." Everything downstream — the mapping, the branching, the error handling — is inert until a trigger fires. Chapter 3 (Mental Models: How a Run Actually Happens) walked through what happens after ignition; this chapter is about the ignition itself, in mechanical detail, because the differences between the three platforms are larger here than almost anywhere else, and they have real consequences for latency, cost, and reliability.

There are four families of trigger, and all three platforms offer all four, under different names and with different mechanics:

  1. Polling triggers — the platform repeatedly asks an app "anything new?" on a timer.
  2. Instant triggers — the app pushes a notification to the platform the moment something happens, using a webhook (an automatic app-to-app web notification, unpacked below) under the hood.
  3. Schedule triggers — a clock starts the workflow at times you define, with no external event at all.
  4. Manual and on-demand starts — a human (or another workflow) presses a button.

We will take each in turn, then compare latency and polling frequency across platforms and plans, and close with guidance on choosing. Two boundary notes so you know what lives elsewhere: raw inbound webhooks that you wire up yourself — a bare URL you hand to any system that can send an HTTP request — are the subject of Chapter 9 (Webhooks and Raw HTTP). And anything about pausing, delaying, or throttling a run that has already started belongs to Chapter 17 (Waiting, Scheduling Windows, and Throttling). This chapter is strictly about how runs begin.

The Four Families at a Glance

Family Who initiates Typical latency Zapier name Make name n8n name
Polling The platform, on a timer Minutes (plan-dependent) Unlabeled trigger (polling is the default) "Watch" modules on a schedule Polling trigger nodes with poll times
Instant The connected app, via webhook Seconds Trigger labeled "Instant" Instant modules, lightning-bolt badge Trigger nodes on an active workflow
Schedule A clock inside the platform At the scheduled moment Schedule by Zapier Scenario scheduling settings Schedule Trigger node
Manual A person or another workflow Immediate Editor test, Chrome extension button, Transfer Run once, on-demand scheduling Execute workflow button, Manual Trigger node

The vocabulary differs, but the physics are identical: something has to notice an event, and that something is either the platform (polling), the app (instant), a clock (schedule), or you (manual).

Polling Triggers: The Platform Asks on a Timer

Polling is the oldest and most universal trigger mechanism. The platform calls the connected app's API — its application programming interface, the doorway apps expose for software-to-software requests — at a fixed interval and asks for recent records: recent rows, recent emails, recent deals, whatever the trigger watches. If the response contains records the platform has not seen before, each new record starts a run. If nothing is new, the poll ends quietly and the timer resets.

Polling exists because it makes no demands on the app. Any API that can answer "list your recent records" can be polled, which is why nearly every trigger in every catalog has at least a polling version. The costs are latency (nothing happens between polls) and wasted work (most polls find nothing).

How a single poll actually works

A poll is a small, complete transaction. Mechanically:

  1. The platform wakes up at the scheduled moment and sends a request to the app: usually "give me the most recent N records," sometimes "give me records changed since timestamp T."
  2. The app returns a list — often empty, sometimes containing a mix of records the platform has already processed and genuinely new ones.
  3. The platform compares each returned record against its memory of what it has already seen.
  4. Every record judged new becomes a trigger event. What one event starts differs by platform: on Zapier, each new record starts its own Zap run; on Make, all the new records from one poll travel as bundles within a single scenario run; on n8n, they travel as items through a single execution. (Chapter 11, Three Data Models, is entirely about this difference.)
  5. The platform updates its memory and goes back to sleep.

Step 3 is the interesting one, because "new" is not as obvious as it sounds.

Deduplication: how the platform decides what is new

Every polling system needs deduplication — a memory of which records it has already fired on, so the same record does not trigger the workflow again on every subsequent poll. The three platforms implement this memory differently, and the differences explain most polling surprises you will ever hit.

Zapier keeps a rolling memory of record identifiers per Zap (a Zap is Zapier's word for a workflow). When a poll returns records, Zapier reads each record's id field — the unique identifier the app assigned — and checks it against the Zap's seen list. Unseen ID: fire. Seen ID: skip. Two consequences follow. First, if a record is edited, its ID does not change, so a "new record" trigger will not fire again — that is why catalogs offer separate "new record" and "updated record" triggers, with the updated variety typically watching a modification timestamp instead. Second, the seen-list is attached to the Zap's trigger configuration: significantly reworking the trigger step, or in some cases turning the Zap off for a long stretch and back on, can reset or age out that memory, and the trigger may treat some recent records as new again.

Make (the platform formerly named Integromat — you will still see the old name in older tutorials) makes the memory visible and hands you the controls. Polling trigger modules in Make are usually named "Watch …" ("Watch Rows," "Watch Events"), and each one keeps a pointer called the epoch: the position in the record stream up to which everything counts as already processed. When you first add a watch module — and any time afterward — you can right-click it and use Choose where to start to set the epoch: from now on, from a specific date, from a specific record, or from the beginning of everything. Each successful poll advances the pointer. This explicitness is a genuine advantage: backfilling a month of missed records is a two-click operation on Make, where on Zapier it requires a separate bulk-import tool.

n8n stores polling state inside the workflow itself, in what its documentation calls workflow static data: typically the timestamp of the last successful poll or the identifier of the last record fired on. Each polling trigger node (Gmail Trigger and its siblings) checks new results against that stored state. Because n8n can be self-hosted — you run the software on your own server rather than renting the vendor's — this state lives in your own database. One subtlety: static data is saved only by production runs of an active workflow; manual test runs in the editor do not update it, and reset behavior after deactivating and reactivating varies by node, so check the node's documentation before relying on it.

Watch out: Turning a polling trigger on does not backfill history — on all three platforms the default is "only records that appear from now on." The inverse trap is worse: on Make, setting Choose where to start to "All" on a watch module pointed at a large table fires once per historical record, and can burn a month's worth of credits in a single run. (A credit is the unit Make bills in — roughly one per standard module run, with AI and some specialty modules costing more. Make billed in operations until an August 2025 change swapped in credits at a 1:1 rate, so older tutorials still say "operations.") Decide deliberately where the pointer starts before you activate anything.

Deduplication also has known blind spots worth naming once so they do not bite you later. If an app reuses identifiers (rare, but it happens with sequential numbering after deletions), a genuinely new record can be silently skipped because its ID was seen before. If a poll returns only the most recent N records and more than N arrived between polls, the overflow may never be seen at all — a real risk on slow polling intervals against busy systems, and one of the arguments for instant triggers at scale (Chapter 30, Scale, Volume, and Performance). And if a record is created and deleted between two polls, no platform will ever know it existed.

Polling latency and how plans change it

The defining cost of polling is the gap between the event and the poll that notices it. On average the delay is half your polling interval; at worst it is the whole interval.

Tip: When a stakeholder asks "how fast will this react?", answer with the polling interval, not with hope. A trigger polled every fifteen minutes has an average reaction time around seven or eight minutes and a worst case of the full interval. If that number makes anyone wince, you need an instant trigger or a webhook (Chapter 9), not a faster promise.

Instant Triggers: The App Pushes

An instant trigger inverts the arrangement. Instead of the platform asking on a timer, the connected app sends a message the moment the event happens. Under the hood this is a webhook: the platform gives the app a private URL, the app registers it as a notification destination (a step called a webhook subscription, which the platform performs automatically through the app's API when you activate the trigger), and from then on the app fires an HTTP request at that URL whenever the watched event occurs. Latency drops from minutes to seconds, and the platform does no wasted work between events.

The catch: the app must support push. The vendor has to have built a webhook subscription API, and the platform's integration has to have implemented it. That is why catalogs are a patchwork — the same app may have an instant "new message" trigger and a polling-only "new contact" trigger, simply reflecting what the vendor exposes.

How to recognize them:

Two mechanical caveats keep instant triggers honest. First, delivery is usually at-least-once, not exactly-once: apps may occasionally resend the same event (network retries), so idempotency — designing the workflow so processing the same event twice is harmless — matters more here than with polling; Chapter 19 (Error Handling by Design) covers the patterns. Second, if the platform is unreachable when the app pushes (an outage, a self-hosted n8n server that is down), the event may be retried by the sender or may be lost, depending entirely on the sending app's retry policy. Some integrations pair a webhook with a periodic safety-net poll; most do not. Chapter 28 (Diagnosing Failures) covers how to detect the gap after the fact.

Tip: When both a polling and an instant version of the same trigger exist, take the instant one unless you have a specific reason not to. It is faster, cheaper in polling overhead, and immune to the "more events than the poll window" overflow problem. The reasons to prefer polling are narrow: you want deliberate batching, or the instant variant is marked beta and the polling one is battle-tested.

If the app you need offers no instant trigger at all but does let you configure an outgoing webhook in its own settings screen, you can bypass the catalog entirely and point that webhook at a URL you create on the platform. That is the raw-webhook pattern, and it is exactly what Chapter 9 (Webhooks and Raw HTTP) teaches.

Schedule Triggers: Workflows on a Clock

A schedule trigger starts a workflow at times you define, with no external event and no incoming data beyond the timestamp itself. This is how you build digests ("every morning at 8, summarize yesterday's orders"), housekeeping ("every Sunday night, archive closed tickets"), and periodic pulls from systems that cannot push. All three platforms treat schedules as first-class, but they house them in different places.

Schedule by Zapier

Zapier packages its clock as a built-in app called Schedule by Zapier. You select it as the trigger, pick a cadence — every hour, every day, every week, or every month — and then the specifics: time of day, day of week, whether to include weekends. Each tick starts one Zap run whose trigger data is just the date and time. Zapier deliberately keeps this simple; there is no cron syntax and no "every 20 minutes on weekdays" in the native trigger. For odd cadences, Zapier builders combine Schedule with a filter step (Chapter 16, Branching: Filters, Paths, and Merges) — for example, trigger hourly and filter to proceed only when the hour matches a list.

Make: scheduling is a property of the scenario

Make does not use a schedule module for this at all — scheduling is a setting on the scenario itself, the clock icon attached to the trigger module. Open it and you choose among options along these lines: at regular intervals (every N minutes, bounded by your plan's minimum), once at a specific date and time, every day at set times, on specific days of the week, on specific days of the month, or On demand (the scenario runs only when started manually or through Make's API). There is also an advanced mode where you can restrict any of these to time windows — a between-hours restriction, specific months — which covers most of what cron does elsewhere, in form-based clothing.

The elegant consequence of this design: for a polling scenario, the schedule is the polling interval, as noted earlier. The slightly confusing consequence: a scenario that starts with a "Watch" module and a scenario that starts with a schedule-driven "Search" module can look nearly identical, but the first deduplicates via its epoch pointer while the second fetches whatever matches its query every time, with no memory. When you want "process each new row exactly once," you want the watch module; when you want "every morning, fetch today's report regardless," you want a scheduled search.

n8n: the Schedule Trigger and cron in plain English

n8n's clock is the Schedule Trigger node. In its friendly mode you pick an interval unit — seconds, minutes, hours, days, weeks, or months — plus the specifics (which day, what time). In its custom mode you write a cron expression, and this is worth demystifying because cron shows up throughout the automation world.

A cron expression is five values separated by spaces, read left to right as: minute, hour, day of month, month, day of week. Each position holds a number, a * meaning "every," a list like 1,15, a range like 1-5, or a step like */10 meaning "every tenth." Reading a few makes the pattern click:

Expression Plain English
0 9 * * * At minute 0 of hour 9, every day — 9:00 a.m. daily
30 8 * * 1-5 8:30 a.m., Monday through Friday (days 1–5)
*/10 * * * * Every 10 minutes, around the clock
0 0 1 * * Midnight on the 1st of every month
0 18 * * 5 6:00 p.m. every Friday

n8n also accepts a six-field variant with a leading seconds position, so if an expression you paste from elsewhere fires oddly, count its fields first.

Watch out: In standard cron, day-of-month and day-of-week are combined with OR, not AND, when both are restricted. 0 9 13 * 5 does not mean "9 a.m. on Friday the 13th" — it means 9 a.m. on every 13th and 9 a.m. every Friday. If you need the intersection, schedule on one dimension and check the other inside the workflow with a filter or IF step (Chapter 16).

Timezones: where "9 a.m." is decided

Every schedule needs to know whose 9 a.m. you mean, and each platform answers differently:

Watch out: Daylight saving time is the classic silent scheduler bug. A workflow scheduled at 2:30 a.m. in a zone that skips from 2:00 to 3:00 one night a year may not run that night, or may run twice on the fall transition, depending on the platform's handling. If a nightly job is genuinely critical, schedule it at an hour that exists year-round in your zone — and monitor for the run's absence (Chapter 27, Monitoring, History, and Alerting) rather than assuming.

Manual and On-Demand Starts

The fourth family is the humble button. Manual starts matter more than they first appear: they are how you test, how you run supervised one-off jobs, and how you build "a human decides when" into a process without building approval machinery (that machinery is Chapter 20, Humans in the Loop).

n8n is the most manual-friendly of the three. The Execute workflow button in the editor (labeled Test workflow in some versions) runs the workflow immediately, right there, with the data flowing visibly through each node — this is the heart of n8n's build-test loop, covered properly in Chapter 26 (Testing, Debugging, and Launch). There is also a dedicated Manual Trigger node for workflows that should only ever run when a person clicks, and n8n workflows can start other workflows on demand — the sub-workflow pattern of Chapter 18 (Modularity and Reuse).

Make gives every scenario a Run once button in the scenario editor, which executes the scenario immediately regardless of its schedule — including polling scenarios, which will poll right now and process whatever the epoch pointer says is new. Pairing Run once with the on demand scheduling option produces a scenario that never runs unattended: a supervised tool rather than an automation, which is exactly right for risky operations like bulk updates.

Zapier is the least on-demand by design; Zaps are meant to be always-on responders rather than tools you invoke. Your manual options are: the editor's test controls (testing the trigger only fetches a real sample record; continuing on to test the action steps performs those actions for real), the Zapier browser extension's push-button trigger (a trigger app whose event is "I clicked the button in my browser"), buttons inside Zapier's own Tables and Interfaces products, and Transfer, Zapier's separate bulk-run tool for pushing existing records through a Zap's actions — the sanctioned answer to "I turned the Zap on late and need to process last month's rows."

Tip: Before any trigger goes live, run the workflow manually with a real record and read the output end to end. All three platforms make this cheap — Execute workflow, Run once, or the editor test — and it catches the large class of bugs that only appear with real data shapes. Chapter 26 turns this habit into a discipline.

Latency and Polling Frequency: The Cross-Platform Picture

Pulling the threads together, here is how fast each start mechanism actually reacts, and who controls the dial:

Mechanism Zapier Make n8n
Instant trigger Seconds; no plan gate on speed Seconds; no plan gate on speed Seconds; workflow must be active, server must be reachable
Polling trigger Default interval set by plan tier; per-Zap adjustment on paid tiers Interval = scenario schedule; minimum interval set by plan Interval set per node; effectively unrestricted self-hosted, execution-metered on Cloud
Schedule Fires at the scheduled minute Fires at the scheduled time, within plan's minimum-interval bounds Fires per cron/interval, to-the-second options available
Manual Editor test, extension button, Transfer Run once, immediate Execute workflow, immediate

Three observations turn this table into judgment:

First, for time-sensitive work, the trigger family matters more than the platform. An instant trigger on any of the three reacts in seconds; a polling trigger on any of them reacts in minutes. If a lead should get a reply while they are still at their desk (the scenario Chapter 36 builds three ways), the deciding question is "does this app offer an instant trigger or an outgoing webhook?" — not "which platform is fastest?"

Second, who controls the polling dial differs, and it shapes cost. On Zapier the fast intervals live on the higher tiers: you buy speed by upgrading, then fine-tune individual Zaps within what your plan allows. On Make you tune it per scenario and pay in credits: polling twice as often costs roughly twice the credits for watch-and-find-nothing cycles on busy schedules. On self-hosted n8n frequent polling is free at the platform layer but spends your server's capacity and the target API's rate-limit goodwill. Chapter 31 (Unit Economics) prices these differences properly.

Third, latency variance is a property of polling, not a defect in your build. The same Zap will react in one minute on Monday and twelve on Tuesday purely by where the event lands in the poll cycle. If you see that spread in your run history, nothing is wrong — that is the mechanism. Confirm which family a trigger belongs to before you spend an afternoon "debugging" it (Chapter 28 gives the fuller diagnostic tree).

Choosing a Trigger: A Short Decision Path

For any new workflow, walk this order:

  1. Does the event need a reaction in seconds? Use an instant trigger if the catalog has one; if not, check whether the source app can send an outgoing webhook to a URL you create (Chapter 9). Only if neither exists, fall back to the fastest polling your plan allows — and say the honest latency number out loud to whoever owns the process.
  2. Is a delay of minutes acceptable? Polling is fine, and it is often the simpler choice: no webhook registration to go stale, easy re-pointing of the dedupe memory on Make, no dependency on your n8n server being reachable at the moment of the event.
  3. Is the work periodic rather than event-driven? Use a schedule — Schedule by Zapier, Make's scenario scheduling, or n8n's Schedule Trigger — and set the timezone deliberately rather than by default.
  4. Should a human decide each time? Make it manual: on-demand scheduling plus Run once on Make, a Manual Trigger workflow on n8n, a button-style trigger or Transfer on Zapier.

One final framing to carry into the rest of Volume B. A trigger is a contract with three clauses: what event counts (the trigger type and its filters), how it is noticed (poll, push, clock, or click), and what data arrives with it (the trigger's output fields, which Chapter 12 teaches you to map). Most trigger frustration in real teams traces to clause two — an instant trigger assumed where a poll exists, a poll interval nobody knew was plan-gated, a schedule firing in the wrong timezone. You now know how to read that clause on all three platforms. Next, Chapter 9 takes the one trigger type powerful enough to deserve its own chapter — the raw webhook you wire yourself — and shows you how to connect anything that can speak HTTP.


Webhooks and Raw HTTP

Every app catalog runs out eventually. The service you need has no connector, or the connector exists but is missing the one endpoint you care about, or you built the internal tool yourself and no catalog on earth will ever list it. When that happens, all three platforms hand you the same escape hatch: raw HTTP — the plain protocol the entire web runs on. Learn it once and no missing connector can stop you again.

This chapter owns that technique for the whole compendium. It runs in two directions. First, receiving: turning your workflow into a web address that other systems can call, so anything that can send a web request can start your automation. Second, sending: making your workflow call any web API directly, with authentication, even when no connector exists. Then it closes with the unglamorous skills that separate a demo from a production system — pagination, rate limits, retries, and reading error codes. Later chapters lean on this one and never re-teach it: custom connectors build on it in Chapter 10 (When the Catalog Falls Short: Custom Connectors and Code Steps), and error-handling strategy picks it up in Chapter 19 (Error Handling by Design).

First, the vocabulary

HTTP (HyperText Transfer Protocol) is the request-and-response language of the web. One party — the client — sends a request to an address; the other party — the server — sends back exactly one response. That is the whole ceremony. Every request has four parts:

Every response carries a three-digit status code summarizing how it went (200 means success; more on the full cast later), plus its own headers and usually a body.

A webhook is nothing more than this same mechanism pointed at you: instead of your workflow asking a service "anything new?" over and over (polling, from Chapter 8, Triggers: How Workflows Start), the service sends an HTTP request to a URL you own the moment something happens. The data it sends is called the payload. Webhooks are how instant triggers work under the hood on all three platforms; this chapter is about wiring them by hand.

Receiving: a URL that runs your workflow

The catch-hook pattern

All three platforms implement the same idea with different names: the platform mints a long, unguessable URL; you paste that URL into the sending system (a form tool, a payment provider, your own app, a colleague's script); every request that arrives at the URL starts a run, with the payload as the trigger data. Think of it as giving your workflow a phone number.

Zapier Make n8n
Building block Webhooks by Zapier trigger, Catch Hook Webhooks app, Custom webhook module Webhook node
Raw-body variant Catch Raw Hook (unparsed body, for signatures) Enable header/raw options in webhook settings Raw body option on the node
Email-in variant Email by Zapier (separate built-in) Custom mailhook (an email address as a trigger) No direct equivalent; use an email trigger node
Custom reply to caller No — fixed acknowledgment only Yes — Webhook response module Yes — Respond to Webhook node
Test vs. live URL One URL One URL per webhook Separate Test URL and Production URL

Zapier. Create a Zap and choose Webhooks by Zapier as the trigger with the Catch Hook event. Zapier shows you a URL under hooks.zapier.com — copy it into the sending system, send a sample request, and Zapier's test step will find it. Note that Webhooks by Zapier is treated as a premium built-in app, so expect it to require a paid plan. Zapier parses the incoming JSON (or form-encoded data — the key=value&key2=value2 format an old-fashioned HTML form submits) into fields you can map in later steps. If you need the byte-for-byte original body — you will, for signature verification — use the Catch Raw Hook event instead, which hands you the raw text unparsed.

Make. In a scenario, add the Webhooks app and choose Custom webhook, then click Add to create and name a new webhook. Make gives you a URL under its hook domain; copy it out. Make learns the payload's shape from the first request it sees — send one sample and the fields become mappable in later modules. If the sender's format changes later, use the webhook's Redetermine data structure option to re-learn it. Make's distinctive extra is the Custom mailhook: instead of a URL, Make mints an email address, and any message sent to it triggers the scenario with the subject, body, sender, and attachments as trigger data — a genuinely handy trick for systems that can send email but not HTTP.

n8n. Add a Webhook node to a workflow. It offers two URLs: a Test URL, which only listens while you are actively executing the workflow in the editor (perfect for building), and a Production URL, which only listens once the workflow is toggled active. Sending your test payloads to the production URL while the workflow is inactive is the classic first-day mistake — the caller gets back a "webhook is not registered" error, nothing appears in the editor, and no run is recorded. The node lets you choose the HTTP method to accept, the URL path, and how to respond (more below). If you self-host n8n, remember the URL is only reachable from the outside world if your instance is — see Chapter 32 (Hosting, Security, and Compliance) for exposure trade-offs.

Tip: Whatever the platform, your first move after creating a catch-hook is always the same: send yourself a realistic sample request and look at what arrived. Use any HTTP client — curl on the command line, a tool like Postman, or even another workflow. Never build the downstream steps against a payload you imagined; build them against one you caught.

Inspecting what arrived

A webhook payload has three layers worth looking at, and beginners usually only look at one. The body is the headline data. The headers tell you who is calling and how — content type, user agent (the sender identifying its own software), and crucially any signature the sender includes. The query string (the ?key=value part of the URL) is a third channel senders sometimes use for tokens or routing hints. Zapier's catch hook exposes querystring parameters as fields; Make's webhook settings let you opt in to receiving headers alongside the body; n8n's Webhook node returns body, headers, and query as separate sections of the item.

Payload shapes vary wildly. Some senders post tidy JSON. Others send form-encoded data, XML, or JSON wrapped inside a single form field as a string — a surprisingly common pattern that leaves you with one giant text field until you parse it (Chapter 12, Mapping and Transforming Fields, covers the parsing tools). When a payload looks wrong, suspect the sender's content-type header first: if it says form data but the body is JSON, the platform will mis-parse it.

Replying to the caller

By default all three platforms answer the sender immediately with a simple success acknowledgment, then run your workflow. Usually that is exactly right: webhook senders want a fast 200 OK and will treat slow answers as failures. But sometimes the caller genuinely needs an answer computed by the workflow — you are building a small API of your own, or a form widget wants JSON back to display.

Watch out: If you reply from the end of a long workflow, the caller waits the whole time, and most senders time out after a modest number of seconds. Keep the path from webhook to response short, and move slow work after the response (or into a second workflow). Chapter 17 (Waiting, Scheduling Windows, and Throttling) covers deliberate delay; this is the opposite discipline.

Securing an open URL

A catch-hook URL is a door with no lock: anyone who has the string can start your workflow and feed it arbitrary data. The URL's unguessability is real protection against strangers — treat the URL itself as a secret, never post it publicly, and regenerate it if it leaks — but it is not protection against a leak, a log file, or a departing contractor. Layer your defenses:

Shared secret. Agree on a token with the sender, delivered in a header (best) or query parameter (acceptable). First step of the workflow: compare the received value with the expected one and stop if it differs — a filter in Zapier or Make, an If node in n8n. n8n's Webhook node goes further and can enforce this before the workflow even runs: it supports built-in authentication options on the node itself, including basic auth and a required header value.

Signature verification. Serious senders (payment providers are the canonical example) sign each delivery: they compute an HMAC — a hash-based message authentication code, a cryptographic fingerprint of the exact body computed with a secret key — and send it in a header. You recompute the fingerprint from the raw body using your copy of the key; if they match, the payload is authentic and untampered. This is strictly stronger than a shared secret, because the signature changes with every payload and proves the body was not altered in transit. Mechanics per platform: in Zapier, use Catch Raw Hook plus a Code by Zapier step to compute and compare the HMAC (Chapter 10 covers code steps); in n8n, a Code node after the Webhook node with raw body enabled; in Make, the built-in hashing functions can compute keyed hashes in a filter, though anything intricate is easier in a code-capable step. The sender's documentation always specifies the exact recipe — which header, which hash algorithm, what to concatenate. Follow it literally; a signature check that is almost right fails every time.

Narrow the aperture. Accept only the HTTP method you expect. If the platform or your hosting layer supports it, restrict calling IP addresses. Validate the payload's shape before acting on it — a required field missing is a reason to stop, not to improvise.

Expect duplicates. Webhook senders deliver at-least-once: network hiccups make them retry, so the same event can arrive twice. If your workflow does anything non-repeatable — charging, emailing, creating records — dedupe on an event ID from the payload before acting. Chapter 14 (Storing Data Inside the Platform) shows where to keep the seen-ID list.

Tip: Whatever you verify, verify it first. A security check as step seven protects nothing that steps one through six already did.

Sending: speaking HTTP yourself

Now the other direction: your workflow as the client, calling an API no connector covers. This is where the vocabulary section pays off, because a raw HTTP step is just a form with five blanks — URL, method, headers, body, and authentication — and the API's documentation tells you what goes in each.

Reading an API's documentation like a native

Every REST API (REST — Representational State Transfer — is the dominant style of web API: resources at URLs, manipulated with HTTP methods) documents its endpoints the same way. GET /v1/contacts lists contacts; GET /v1/contacts/42 reads one; POST /v1/contacts creates one from a JSON body; PATCH updates; DELETE removes. GET requests put their inputs in the query string and carry no body; POST and friends carry a JSON body and declare it with a Content-Type: application/json header. That one header omission — forgetting the content type on a POST — is behind a remarkable share of "the API ignores my data" mysteries, because the server reads the body as the wrong format or not at all.

Status codes are the API's tone of voice, and you will triage failures by them for as long as you do this work:

Code Meaning Whose problem
200 / 201 / 204 Success (OK / created / success with no body) Nobody's
301 / 302 Redirect — the resource lives elsewhere Usually handled automatically
400 Bad request — malformed body or parameters Yours
401 Unauthorized — missing or invalid credentials Yours
403 Forbidden — valid credentials, insufficient permission Yours (or your API plan's)
404 Not found — wrong URL or nonexistent resource Yours
409 / 422 Conflict / semantically invalid — right shape, wrong content Yours
429 Too many requests — you hit a rate limit Yours, but fixable by slowing down
500 / 502 / 503 / 504 Server error, bad gateway, unavailable, gateway timeout Theirs

The deep rule: 4xx means the request is wrong — retrying the identical request is pointless. 5xx means the server is struggling — the identical request may well succeed in a minute. Everything in the robustness section builds on that distinction.

Authentication, three flavors

Chapter 7 (Connections and Credentials) covered how platforms store credentials; here is how raw requests present them. Three patterns cover nearly every API you will meet:

Where each platform wants these: Zapier's webhook actions provide basic-auth fields and a free-form headers section for bearer tokens and API keys. Make's HTTP app splits by flavor — alongside the plain Make a request module there are dedicated variants for basic auth, API-key auth, and OAuth 2.0 that store the credential in Make's managed storage (a keychain for basic and API-key auth, a connection for OAuth) instead of leaving secrets sitting in plain scenario fields. n8n's HTTP Request node is the most elegant of the three: besides generic credential types (basic, header, query, OAuth) it offers a predefined credential type option that lets a raw request borrow any of n8n's hundreds of stored app credentials — so you can call an obscure endpoint of an app n8n already knows, authenticated, without re-entering secrets.

Watch out: Never paste a live API key directly into a URL, a step's plain-text field, or a workflow name. Keys in URLs leak into logs and run histories. Use each platform's credential store (Chapter 7), and if a key ever does land somewhere visible, rotate it — assume anything logged is compromised.

One call, three ways

To make this concrete, here is the same real request on each platform. The target is Open-Meteo, a free public weather API that requires no key — ideal for practice. The goal: fetch current weather for Berlin.

The raw request, expressed as curl (the standard command-line HTTP client, and the lingua franca of API documentation):

curl "https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41&current_weather=true"

A successful response is 200 with a JSON body containing a current_weather object — temperature, wind speed, a weather code, and a timestamp.

Zapier. Add an action step, choose Webhooks by Zapier, event GET. Put the base URL in the URL field and add latitude, longitude, and current_weather as query-string parameters in the provided key/value rows (or paste the full URL, query string and all). Leave auth and headers empty — this API needs none. Test the step; Zapier flattens the JSON response into mappable fields like current_weather__temperature, using its double-underscore convention for nested data (Chapter 11, Three Data Models). For anything beyond simple GET/POST, choose the Custom Request event, which exposes method, headers, and raw body directly.

Make. Add the HTTP app's Make a request module. URL: the full address including the query string. Method: GET. Turn Parse response on so Make converts the JSON into a structured bundle you can map — with it off, you get one opaque text blob. Run once; downstream modules can now map current_weather.temperature from the module's output.

n8n. Add an HTTP Request node. Method GET, URL as above — either pasted whole or with the query parameters entered in the node's query-parameters section, which keeps them readable. n8n even has an import cURL convenience: paste a curl command from any API's docs and the node configures itself, which is the fastest way to go from documentation to working call anywhere in this book. Execute the node; the JSON appears as structured output for the next node.

If the API had required auth, the shape barely changes: a bearer token becomes one Authorization header in Zapier, a keychain credential on Make's auth-specific module, and a credential selection on n8n's node. The five blanks stay the same blanks.

Robustness: the difference between a demo and a system

A call that works once is a demo. These four disciplines make it dependable.

Pagination

APIs refuse to return ten thousand records in one response; they return a page — a bounded chunk — plus instructions for getting the next one. Three schemes dominate. Page numbers (?page=3&per_page=100): increment until a page comes back empty or short. Offset/limit (?offset=200&limit=100): same idea with a record count instead of a page count. Cursors: each response includes an opaque token (sometimes in the body, sometimes in a Link header) that you send back to get the next chunk; you are done when no token is returned. Cursor pagination is the most reliable because it tolerates records being added or removed mid-walk.

Platform reality check: n8n's HTTP Request node has built-in pagination support in its options — you describe how the next-page token or page number is derived, and the node walks the pages for you and returns the combined items. In Make, catalog app modules often paginate internally, but for raw HTTP you build the loop yourself — with the Repeater module (which emits a numbered sequence you can turn into page requests) or a repeat-until-empty structure. In Zapier, looping over an unknown number of pages inside one run fights the product's grain; small fixed page counts can be unrolled, but genuine pagination usually belongs in a code step or a different design. Chapter 13 (Lists, Loops, and Aggregation) owns the looping mechanics; the takeaway here is simply that a heavy pagination job is a point in n8n's favor when you are choosing a platform for it.

Rate limits

Every API caps how fast you may call it — per second, per minute, or per day. Exceed the cap and you get 429 Too Many Requests, often with a Retry-After header telling you how many seconds to wait, and frequently companion headers (names vary by API) showing your remaining allowance. Rate limits are not errors in your logic; they are the API asking you to slow down.

Your levers: spread work out rather than bursting (n8n's HTTP Request node has batching options that insert a pause between groups of requests; Make scenarios naturally process bundles sequentially; in Zapier, deliberate pacing is a design exercise — Chapter 17 covers throttling patterns on all three). And when a 429 does arrive, treat it as retryable with a wait — which brings us to backoff.

Retry with backoff

When a request fails with a 5xx or a 429, the right move is to wait and try again — but naively retrying in a tight loop makes an overloaded server more overloaded. The standard remedy is exponential backoff: wait briefly before the first retry, double the wait each subsequent attempt, and give up after a handful of tries. Production-grade implementations add jitter — a small random wobble in each wait — so that many clients knocked back at the same moment do not all return in the same synchronized wave.

On n8n, retry is a node-level setting: enable retry-on-fail on the HTTP Request node and configure the number of attempts and the wait between them. On Make, retry is built from error-handler routes — the break-and-retry pattern that stores the failed execution and re-runs it later. On Zapier, a failed action errors the run, and recovery leans on the platform's replay machinery for failed runs, available on higher-tier plans. The full strategy layer — dead-letter paths (parking failed items somewhere a human can review them), alerting, partial-failure design — is Chapter 19's territory; what belongs to this chapter is the reflex: 5xx and 429, retry with growing waits; 4xx, stop and fix the request.

Tip: Make retried requests safe to repeat. A retried GET is always harmless; a retried POST can create the same record twice. Many APIs accept an idempotency key — a unique token you attach to a write so the server can recognize and ignore a duplicate attempt. If the API offers one, use it; if not, check-before-create or dedupe downstream.

Reading errors like a mechanic

When a raw HTTP step fails, resist the urge to fiddle. Read three things in order. The status code tells you whose fault it is (the table above). The response body usually says exactly what is wrong — APIs return error JSON like {"error": "missing required field: email"}, and that sentence is worth an hour of guessing. Your request as actually sent — the platform's run history shows it — catches the gap between what you meant to send and what the mapping produced: an empty field, a stray quote, a number sent as a string.

Two platform-specific traps deserve flagging. Make's plain HTTP module does not necessarily treat a 4xx/5xx status as a module failure unless you enable its option to evaluate all response states as errors — leave that off and a 404 sails through as a "successful" bundle whose status-code field nobody checks, corrupting everything downstream. And on any platform, a 401 on a call that worked yesterday is almost never your workflow's fault: tokens expire, keys get rotated, OAuth grants get revoked. Check the credential before you touch the step. Deeper diagnostic method — reproducing failures, bisecting workflows, reading platform logs — lives in Chapter 28 (Diagnosing Failures), and the symptom-indexed lookup is Chapter 39 (The Troubleshooting Encyclopedia).

What you can now do

You can point any system at a URL and have it start your workflow, prove the caller is who they claim to be, and answer them with a computed response on the platforms that allow it. You can call any documented API with any of the three common credential styles, and you know the five blanks every raw request reduces to. And you know the production reflexes: paginate to completion, respect the rate limit, back off and retry on 5xx and 429, stop and read the body on 4xx.

Raw HTTP is the floor under everything connective in this book. When Chapter 10 wraps these techniques into reusable custom connectors, when Chapter 21 (AI Steps Inside Ordinary Workflows) calls a model provider's API directly, when Chapter 36's worked project needs one endpoint the catalog lacks — they will all assume, and never re-explain, exactly what you have just learned.


When the Catalog Falls Short: Custom Connectors and Code Steps

Every platform's app catalog eventually runs out. You hit a niche industry tool nobody has integrated, an internal system your company built ten years ago, or an API endpoint the official connector simply doesn't expose. Chapter 9 (Webhooks and Raw HTTP) gave you the first escape hatch: calling any web API directly with an HTTP step. This chapter covers the two escape hatches that remain when raw HTTP isn't enough — building a proper connector of your own, and writing small pieces of code inside your workflows.

These two tools solve different problems. A custom connector solves a reuse problem: you've built the same fiddly HTTP calls in six different workflows, and you want them packaged into a clean, reusable app with its own icon, its own credential storage, and dropdowns instead of raw JSON. A code step solves a logic problem: some transformation or decision is genuinely awkward to express in no-code steps, and five lines of code would do it cleanly. Knowing which problem you actually have — and when the honest answer is "neither, put a small service in the middle" — is the skill this chapter teaches.

The Escalation Ladder, Completed

It helps to see the full ladder of options, from least to most effort. Each rung is worth exhausting before you climb to the next.

  1. Catalog app — someone already built and maintains the connector. Covered in Chapter 6 (The App Catalogs).
  2. Generic HTTP step — you call the API yourself, one request at a time. Covered in Chapter 9 (Webhooks and Raw HTTP).
  3. Code step — a short script inside the workflow handles logic the visual steps can't express cleanly. This chapter.
  4. Custom connector — you package auth, endpoints, and triggers into a reusable app on the platform. This chapter.
  5. Middleware — a small service you host between the platform and the awkward system, doing the heavy lifting outside the platform entirely. This chapter, briefly; the hosting implications live in Chapter 32 (Hosting, Security, and Compliance).

Tip: Before building anything, search the catalog one more time under alternate names — the vendor's old brand, the parent company's name, a community-built variant. Products get renamed, and third parties often publish connectors the official vendor never did. Chapter 6 (The App Catalogs) covers how to judge whether a third-party connector is trustworthy.

What a Connector Actually Is

A connector — Zapier calls the finished product an integration, Make calls it an app, n8n calls it a node — is a package of four things:

When you use an HTTP step, you supply all four of those things by hand, every time, in every workflow. A connector does the work once and hides it. That's the entire value proposition — and also the cost, because now there is a piece of software with your name on it that must be maintained as the underlying API changes.

Building a Connector on Each Platform

All three platforms let you build connectors. What differs is the language you work in, how much of a software project it becomes, and who gets to use the result.

Zapier: the Developer Platform

Zapier's connector-building environment is called the Zapier Developer Platform, and it offers two routes to the same destination.

The first is the Platform UI, a visual, form-based builder that runs in your browser (it lives at Zapier's developer site, separate from the main Zapier editor). You describe your API — the authentication scheme, each action's endpoint and fields, each trigger's polling URL — by filling in forms rather than writing a codebase. There is a code mode for the awkward corners, but for a well-behaved REST API (a web API that uses predictable URLs and standard verbs like GET and POST), a patient non-developer with the API documentation open in another tab can genuinely build a working integration this way.

The second is the Platform CLI — a command-line toolkit where the integration is an ordinary JavaScript project on your own computer. You get full programmatic control: custom request handling, file support, complex pagination (fetching long lists from an API page by page), and real version control with Git. It's the right route for engineers; it's the wrong route if nobody on your team writes JavaScript, because you'll be unable to maintain what you commissioned.

Both routes can produce either a private integration (shared by invitation with specific accounts — the normal choice for internal tools and client work) or a public one (submitted to Zapier's review process and listed in the catalog for everyone). Public listing is a real commitment: Zapier reviews quality and branding, expects the integration to be maintained, and your support inbox will hear about it when the API changes. If you're a software vendor wanting distribution, that's the point — Zapier's directory is the largest of the three and a public integration there is a marketing channel, not just plumbing. That vendor-side world is covered in Chapter 33 (Embedding and Client Work).

Make: Custom Apps

Make's equivalent is the Custom Apps facility. A Make custom app is defined mostly in structured JSON — a text format for describing data — with a templating layer Make inherited from its Integromat days called IML (Integromat Markup Language) for the dynamic parts, like inserting a user's input into a request URL. You describe each module (Make's word for a step), its parameters, its interface, and its communication with the API in these JSON blocks.

There's a web editor for this in Make's developer area, and — tellingly — an official Visual Studio Code extension that lets you develop custom apps in a real code editor with version control. That tells you where Make custom apps sit on the difficulty spectrum: less programming than Zapier's CLI route (you're mostly writing configuration, not logic), but more alien than Zapier's Platform UI, because JSON-plus-IML is its own little dialect you must learn. Developers tend to pick it up in a day or two; non-developers find it steeper than filling in Zapier's forms.

Custom apps are private to your account or organization by default, which is exactly right for internal systems. Publishing publicly to Make's catalog involves a review and approval process with Make, similar in spirit to Zapier's.

n8n: Community Nodes and Custom Nodes

n8n, true to its open-source roots, does connectors differently: a connector is an npm package — a unit of shareable JavaScript code from the Node.js ecosystem (Node.js being the technology that runs JavaScript outside a web browser) — conventionally named n8n-nodes-something. Anyone can write one, publish it to the public npm registry, and anyone running n8n can install it.

This produces three tiers:

Writing an n8n node is a TypeScript project (TypeScript is JavaScript with type annotations that catch mistakes earlier). n8n provides starter templates and two authoring styles — a declarative style, which is mostly configuration and suits straightforward REST APIs, and a programmatic style with full code control for everything else. The skill demanded is squarely "JavaScript developer"; there is no forms-based no-code builder as on Zapier. In exchange you get the loosest publishing model of the three: publishing to npm is instant and requires nobody's approval — only the verified-for-Cloud badge involves n8n reviewing your work.

The Comparison

Zapier Make n8n
Product name Developer Platform (Platform UI or Platform CLI) Custom Apps Community / custom nodes
What you write Web forms (UI) or a JavaScript project (CLI) JSON configuration + IML templating A TypeScript/JavaScript npm package
Skill floor for a simple REST API API-literate non-developer (UI route) Technically confident builder JavaScript developer
Private distribution Invite specific accounts Private to your account/organization by default Install on your own instance
Public distribution Zapier review, then catalog listing Make review, then catalog listing Publish to npm freely; n8n verification needed for Cloud installs
Version control Git-native on the CLI route VS Code extension available Ordinary Git + npm versioning

Watch out: A connector is a commitment, not a craft project. The API you wrapped will change — endpoints deprecate, auth schemes migrate, rate limits tighten — and every workflow built on your connector inherits the breakage. Before building, decide who maintains it, in writing. An orphaned private connector is one of the most common ways automation estates rot; Chapter 29 (Teams, Governance, and Change Management) covers ownership practices.

The Decision Path: HTTP Steps → Connector → Middleware

So when do you actually climb from rung 2 to rung 4? A practical trigger list:

Stay with HTTP steps when the API appears in one or two workflows, the calls are simple, and the people maintaining the workflows can read an HTTP step. Duplication of two steps is cheaper than owning a software package.

Build a connector when you notice any of these: the same authentication dance copy-pasted into five or more workflows; teammates who can't safely edit raw HTTP steps needing to use the API; token refresh logic failing in scattered places (a connector centralizes credentials — one fix, everywhere); or you're an agency provisioning the same client integration repeatedly. The connector converts scattered, fragile knowledge into one maintained artifact. It pairs naturally with the reuse patterns in Chapter 18 (Modularity and Reuse).

Build middleware when even a connector can't carry the weight. Middleware here means a small service you write and host yourself — often a single serverless function (code that a cloud provider runs on demand, so you manage no server) — that sits between the automation platform and the difficult system. The platform makes one clean webhook or HTTP call to your middleware; the middleware does the ugly work and returns a tidy answer.

Middleware wins in four situations:

  1. The logic exceeds what workflow steps should hold — heavy data crunching, large file processing, calls that must fan out to several systems and reconcile the answers.
  2. The same logic must serve multiple platforms. If your business runs Zapier and Make (a common coexistence pattern — see Chapter 34, Migration, Coexistence, and Lock-In), one middleware endpoint serves both; two custom connectors would mean maintaining the same logic twice in two proprietary formats.
  3. The target system's protocol isn't plain HTTP — an old SOAP service (an XML-heavy web protocol from an earlier era), a database wire protocol, an SFTP drop (a secure file-transfer folder). Cloud platforms speak HTTP; your middleware can speak anything.
  4. Secrets or compliance rules forbid putting credentials in a SaaS platform. The platform calls your middleware with one narrow token; the crown-jewel credentials never leave your infrastructure.

The cost is that you now operate a service: deployments, logging, monitoring, and a bus factor — the risk that only one person understands it, and that person leaves. Keep middleware in a version-controlled repository with a README, however small it is.

Tip: A useful tiebreak: connectors package an API; middleware packages a process. If what you're wrapping is "the CRM's API, used politely," build a connector. If it's "fetch from three places, reconcile, apply our business rules, return a verdict," that's a process — put it in middleware, and let the workflow treat it as one step.

Code Inside Workflows

The second escape hatch is smaller and far more common: a code step, where a short script runs inside the workflow itself, receiving data from earlier steps and returning data for later ones.

The case for code steps is concrete. Suppose you need to take a list of order lines, keep only those over a threshold, and produce a comma-separated summary of their product names. In no-code terms that's an iterator or loop, a filter, a text-formatter per item, and an aggregator — four or five steps, each a place to misconfigure something, each consuming task or operation quota (the billing consequences are Chapter 31, Unit Economics). In code it's three lines, and the intent is legible in one glance. The general rule: reach for a code step when the logic is dense but the data is small — parsing odd text, reshaping nested structures, date arithmetic beyond the built-in formatters (Chapter 12, Mapping and Transforming Fields, covers what the no-code formatters can do, and Chapter 13 covers lists and loops; exhaust those first).

The case against: code steps are invisible to non-programmers on your team, they escape the platform's nice per-step debugging views, and they are where workflows quietly become software projects without anyone deciding that. Keep them small, name them descriptively, and comment them as if a stranger will read them — because one will.

Code by Zapier

Zapier's code step is an app in the catalog like any other, called Code by Zapier, offering JavaScript or Python actions. Three facts shape everything you do with it:

Here is a complete, realistic example — cleaning a phone number captured by a form — explained line by line for readers who have never written JavaScript:

// Clean a US phone number from a form into (XXX) XXX-XXXX format.
const phone = inputData.phone || "";
const digits = phone.replace(/\D/g, "");
const last10 = digits.slice(-10);
const pretty = "(" + last10.slice(0, 3) + ") " +
               last10.slice(3, 6) + "-" + last10.slice(6);
output = { formattedPhone: pretty };

The n8n Code Node

n8n's Code node is a core node available on every plan and every hosting mode. It differs from Zapier's in three important ways.

First, it is item-aware. As Chapter 11 (Three Data Models) explains, everything in n8n flows as a list of items. The Code node runs in one of two modes — Run Once for All Items (your code sees the whole list, ideal for filtering and aggregating) or Run Once for Each Item (your code runs per item, ideal for per-record cleanup). This native grasp of lists is why n8n code steps often replace what would be an entire loop construct elsewhere.

Second, the environment depends on where n8n runs. On n8n Cloud you write JavaScript with the built-in helpers (including the Luxon library for dates) but cannot import external npm packages. On a self-hosted instance, an administrator can whitelist any npm packages via an environment variable (NODE_FUNCTION_ALLOW_EXTERNAL), after which your Code nodes can use them — a genuinely large capability jump unique to self-hosting. n8n's Python story has shifted over time: early versions offered a browser-style Python (Pyodide) with a limited package set, which n8n has since replaced — for better security and performance — with real Python, but only through a separate "task runner" helper process that self-hosted administrators must run alongside n8n itself. Treat JavaScript as the first-class citizen and check the current documentation before committing anything important to Python here.

Third, there is no separate mapping-into-inputs ritual: your code addresses the incoming items directly through helpers like $input.

One deliberate limit deserves flagging, because it inverts what the Zapier section just told you: the Code node is not the place to call APIs. n8n's own documentation says you can't make HTTP requests or touch the file system from the Code node, and steers you to the dedicated HTTP Request node (Chapter 9) for calls. Self-hosted instances can work around this by whitelisting a request-making package, but the cleaner pattern on any n8n is: Code node for logic, HTTP Request node for the network.

The same flavor of example, n8n-style — keeping only paid orders and adding a label field, in Run Once for All Items mode:

const items = $input.all();
const paid = items.filter((item) => item.json.status === "paid");
return paid.map((item) => ({
  json: { ...item.json, label: item.json.name + " / " + item.json.total },
}));

Code in Make

Make is the outlier: there is no general-purpose code module on standard plans. This is the platform's philosophy showing — Make's answer to complex logic is its unusually deep visual toolkit of functions inside the mapping panel (Chapter 12 covers these). When visual functions run out, you have four options, in ascending order of commitment:

  1. Custom functions, a feature of Make's top-tier (Enterprise) plans: you define named JavaScript functions in your organization (look for a Functions area in the Make interface, managed by team admins), and then call them inside any mapping field like built-in functions. They support modern JavaScript but no third-party libraries, and their execution budget is measured in milliseconds — these are for transformation logic, emphatically not for making web requests or doing heavy work.
  2. IML functions inside a custom app: if you're already building a Make custom app, you can embed small JavaScript helper functions in it — same spirit, scoped to the app. Note that Make has at times disabled these platform-wide over security concerns and gated re-enablement behind a request to its support team, so confirm current availability before designing around them.
  3. Third-party code-runner apps in Make's catalog: several vendors offer "run JavaScript/Python" modules. These execute your code on the vendor's servers — read that sentence again before pasting customer data into one, and see Chapter 25 (Trust, Cost, and Control) for the evaluation lens.
  4. HTTP to your own function: the universal fallback — a Make HTTP module calling a serverless function you host. This is the middleware pattern in miniature and works on every Make plan.

A custom function example, again line by line — normalizing a product code:

function cleanSku(sku) {
    if (sku === null || sku === undefined) {
        return "";
    }
    return String(sku).trim().toUpperCase();
}

Watch out: Never paste API keys or passwords directly into code steps on any platform. Code step contents are visible to anyone who can open the workflow, are duplicated when workflows are cloned, and escape the platform's credential vault entirely. Use the platform's connection system (Chapter 7) or, where offered, workflow-level variables — and if a secret has already been pasted into a code step, treat it as leaked and rotate it.

The Environments, Side by Side

Code by Zapier n8n Code node Make custom functions
Languages JavaScript or Python JavaScript first-class; Python support varies by version and host JavaScript
Availability All plans All plans, all hosting modes Top-tier plans only
Third-party packages Public npm/PyPI on paid plans (no native modules) Cloud: none; self-hosted: any, admin-whitelisted None
Web requests from code Yes (fetch / requests) No — use the HTTP Request node (self-hosted can whitelist a package) No — budget far too short
Time budget Short — seconds-scale, plan-dependent Governed by workflow and instance settings; roomiest when self-hosted Milliseconds-scale
How data arrives Mapped named inputs, as strings Items via $input, types preserved Function arguments in a mapping
Natural use Transform + light API calls Anything item-shaped; heavy lifting when self-hosted Pure, fast transformations

Tip: Whatever the platform, write code steps as pure functions where you can: data in, data out, no surprises, no side effects like calling APIs mid-transformation. Pure steps are testable by pasting in a sample payload, and they make failures diagnosable in the run history rather than mysterious — Chapter 26 (Testing, Debugging, and Launch) and Chapter 28 (Diagnosing Failures) build on this habit.

The Capability Ceiling, Honestly

Close your eyes to pricing, polish, and preference for a moment and ask only: where does each platform's reach actually end?

Zapier's ceiling is a sandbox ceiling. Between the Developer Platform, Code by Zapier, and raw HTTP, you can integrate essentially any system that speaks HTTP on the public internet. What you cannot do is run native or compiled code, long computations, or reach anything Zapier's cloud can't see — the public npm/PyPI packages you can add on paid plans widen the toolbox but don't move that wall. Its distribution ceiling, though, is the highest: a public Zapier integration puts you in front of the largest automation user base of the three.

Make's ceiling is the most gated. Custom Apps are capable, and the visual function library is genuinely deep — but the moment you need real code inside a scenario, you're either on a top-tier plan, leaning on a third-party code vendor, or calling out to your own middleware. Teams that hit this wall usually don't leave Make; they quietly grow a small serverless sidecar next to it. Budget for that honestly when you compare costs in Chapter 31.

n8n's ceiling is the highest — conditionally. On n8n Cloud, it's roughly comparable to Zapier's with a better code story for item-shaped work. But self-hosted n8n changes the category. Because the software runs on machines you control, it can sit inside your network perimeter and reach what no cloud automation platform can: the on-premises database behind your firewall, the internal API that has no public address, the file server, the license server, the lab instrument gateway. A firewall — the barrier that keeps the public internet out of a private network — stops Zapier and Make at the door, full stop; the standard workarounds are middleware you expose publicly or an agent/tunnel you install inside, both of which are extra systems to secure. Self-hosted n8n simply lives inside, and can additionally run any npm package in its Code nodes and any community node ever published. The price of that reach is that you are now operating infrastructure — updates, backups, scaling, and security are yours. That trade, and whether you should take it, is the subject of Chapter 32 (Hosting, Security, and Compliance).

Capability Zapier Make n8n Cloud n8n self-hosted
Custom connector, private Yes Yes No — only n8n-verified (public) nodes install Yes, unrestricted
Custom connector, public directory Yes, largest reach Yes Yes (verification) Yes (npm + verification)
Code step on entry-level plans Yes No Yes Yes
Arbitrary code packages Public registries only (paid) No No Yes, including native
Reach private networks directly No No No Yes
Who carries operations Vendor Vendor Vendor You

A high ceiling is not an argument by itself — most teams never touch their platform's ceiling, and the day-to-day experience several floors below it matters far more. But when your requirements genuinely include a system behind a firewall, this table stops being trivia and becomes the decision. Chapter 35 (The Decision Framework) shows where capability ceilings belong in the overall choice; Chapter 36 and Chapter 37 then put all three platforms' escape hatches to work on the same real projects, side by side.