# n8n Workflow Auditor - Linter & Security Review (`mediocre_interest/n8n-workflow-auditor`) Actor

Audit n8n workflows for hardcoded credentials, unauthenticated webhooks, expression-injection exposure, missing error handling, deprecated nodes, and unreachable branches. Paste workflow JSON or connect an n8n instance and get one ranked finding per row, plus a health score out of 100 per workflow.

- **URL**: https://apify.com/mediocre\_interest/n8n-workflow-auditor.md
- **Developed by:** [Mediocre\_Interest](https://apify.com/mediocre_interest) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.20 / workflows audited

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## n8n Workflow Auditor — Linter & Security Review for Workflow JSON

Paste an n8n workflow — or point the Actor at your own n8n instance — and get a ranked list of security, reliability, and correctness findings, one row per issue, plus a health score out of 100 per workflow.

It catches the things that only show up in production: an API key typed into a node parameter instead of a credential, a webhook anyone can call, a `typeVersion` two majors behind, a branch that no trigger can reach, and a workflow with no error handling anywhere.

- **Batch.** Audit one pasted workflow, a list of exports, or every workflow on an instance in a single run.
- **Read-only.** Against an instance it calls `GET /api/v1/workflows` and nothing else, and n8n returns credentials as name references without their secret values.

### Rules, not a model

Every finding comes from a deterministic rule written in TypeScript — there is no LLM anywhere in the audit path. The same workflow produces the same findings, in the same order, on every run: nothing drifts between runs, nothing needs re-prompting, and no finding is a judgment call you have to take on faith.

That determinism is what makes the Actor safe to [gate a build on](#using-this-as-a-ci-gate) — a run that passes today passes tomorrow on the same input.

### How to audit an n8n workflow

Give the Actor workflows in any one of three ways — pasted JSON, a URL, or a live instance — or combine all three in one run. Leave **Rule set** and **Minimum severity** at their defaults for the first run; narrowing before you have seen the output usually hides the finding you were looking for.

#### Audit pasted JSON

1. In n8n, open the workflow and use the **Workflow** menu → **Download**. To audit only part of it, select those nodes on the canvas and press `Ctrl+C` instead — n8n copies them as JSON.
2. Paste it into **Workflow JSON**. For several workflows at once, wrap them as `{"workflows": [ ... ]}` — an `n8n export:workflow` bundle already has that shape.
3. Click **Start**. A single workflow takes a few seconds.

#### Audit workflows by URL

1. Put one or more links in **Workflow JSON URLs** — a raw file in a Git repo, a Gist, or an n8n template link. See [Auditing workflows by URL](#auditing-workflows-by-url) for the exact URL shapes accepted.
2. Click **Start**. Each URL is fetched and audited independently; one that returns several workflows is audited — and billed — as several.

#### Audit a live n8n instance

1. Create an n8n API key under **Settings → n8n API** — see [Auditing a live instance](#auditing-a-live-instance) for the required scopes and n8n plan requirements.
2. Fill in **n8n instance URL** and **n8n API key**. Optionally set **Workflow IDs** to audit only specific workflows, or turn on **Active workflows only** to skip deactivated ones.
3. Click **Start**. The Actor only reads: it calls `GET /api/v1/workflows` and nothing else. An instance sweep takes about as long as its slowest page of workflows.

#### Reading the results

1. Open the **report** from the run's Output tab for the whole audit on one page, or read the **Workflow scores** table first if you would rather work in the data — one row per workflow, sorted by health score.
2. Work the **Findings** table top down. It is sorted most severe first, and every row carries the exact node, the parameter path, and a remediation.
3. Suppress what you have decided to live with. Copy the `rule` value from any row into **Ignore rules** and the next run will not report it again.

### What it checks

Twenty rules across six categories. Every finding carries its rule ID, so you can suppress it with `ignoreRules` on the next run.

#### Secrets and credentials

| Rule                   | Severity | What it catches                                                                                                                                                                                         |
| ---------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `secret-in-parameters` | critical | AWS, Slack, OpenAI, Anthropic, GitHub, Google, Stripe, SendGrid, Twilio keys, JWTs and private-key blocks typed into node parameters, plus high-entropy values under names like `apiKey` or `password`. |
| `manual-auth-header`   | high     | An `Authorization` or `X-API-Key` header set literally on an HTTP Request node instead of through a credential.                                                                                         |

#### Security

| Rule                        | Severity | What it catches                                                                                                                      |
| --------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `expression-sandbox-escape` | critical | `constructor.constructor`, `process.env`, `require()`, `globalThis` inside an expression (**CVE-2025-68613**, **CVE-2026-1470**).    |
| `form-expression-injection` | high     | Unauthenticated Form input interpolated into a downstream expression (**CVE-2026-27493**, patched in n8n 1.123.22 / 2.9.3 / 2.10.1). |
| `webhook-no-auth`           | high     | A Webhook node with no authentication and no validator node wired directly to it.                                                    |
| `sql-expression-injection`  | high     | An expression interpolated into an `Execute Query` field instead of using query parameters.                                          |
| `code-node-network-egress`  | medium   | `fetch`, `axios`, `require`, or a hardcoded URL inside a Code node — traffic no credential governs.                                  |

#### Reliability

| Rule                          | Severity      | What it catches                                                                                                                              |
| ----------------------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `no-error-handling`           | medium        | No error workflow, no Error Trigger, and no node with retry or on-error set, while nodes call external services. Reported once per workflow. |
| `loop-without-exit-branch`    | medium        | A Loop Over Items node on a cycle whose "done" output is not connected.                                                                      |
| `http-no-timeout`             | low           | An HTTP Request node with no timeout.                                                                                                        |
| `deprecated-continue-on-fail` | low           | The `continueOnFail` flag n8n replaced with `onError`.                                                                                       |
| `missing-error-workflow`      | medium / info | No error workflow set. `medium` for a workflow on an instance; `info` for pasted JSON.                                                       |
| `http-no-pagination`          | info          | A call to what looks like a list endpoint with no pagination configured.                                                                     |

#### Correctness

| Rule                             | Severity | What it catches                                              |
| -------------------------------- | -------- | ------------------------------------------------------------ |
| `unreachable-node`               | medium   | A node no trigger can reach, so it never runs.               |
| `no-trigger-node`                | medium   | A workflow with no trigger at all.                           |
| `dangling-connection`            | medium   | A connection pointing at a node that is not in the workflow. |
| `disabled-node-on-critical-path` | low      | A disabled node sitting between two connected nodes.         |

#### Versions and supply chain

| Rule                 | Severity      | What it catches                                                                                   |
| -------------------- | ------------- | ------------------------------------------------------------------------------------------------- |
| `deprecated-node`    | high          | A node type n8n has hidden from the panel — `cron`, `function`, `readBinaryFile` and 42 others.   |
| `stale-type-version` | low / medium  | A node behind the current major type version. One major behind is `low`, two or more is `medium`. |
| `unknown-node-type`  | medium / high | A community node dependency. Escalates to `high` when the package is unverified or abandoned.     |

### Input

Ten fields, all optional. Give it workflows in any one of three ways — you can combine them:

```jsonc
{
    // 1. Paste a workflow. For several, wrap them: { "workflows": [ ... ] }
    "workflowJson": { "name": "My workflow", "nodes": [], "connections": {} },

    // 2. Fetch exports from URLs - a Gist, a file in a Git repo
    "workflowUrls": ["https://example.com/workflow.json"],

    // 3. Pull from your own n8n instance
    "n8nBaseUrl": "https://n8n.example.com",
    "n8nApiKey": "<your n8n public API key>",
    "workflowIds": [], // empty = every workflow on the instance
    "activeOnly": true, // only what is actually running

    // Tuning
    "ruleSet": "all", // all | security | reliability | maintainability
    "minSeverity": "low", // info | low | medium | high | critical
    "ignoreRules": ["http-no-timeout"],
}
```

There is nothing else to configure. The node index refreshes itself from n8n on every run, and community-node trust signals are looked up for whichever packages your workflows actually use.

#### Auditing workflows by URL

`workflowUrls` takes any URL that returns workflow JSON — the response does not have to be served as `application/json`, so a raw file in a Git repo works as-is. These are all accepted directly:

| URL                                                                     | What it returns                                                                                                               |
| ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `https://raw.githubusercontent.com/<owner>/<repo>/<branch>/<path>.json` | A workflow exported from the n8n editor, committed to a repo.                                                                 |
| `https://gist.githubusercontent.com/<user>/<id>/raw/<file>.json`        | The same, from a Gist. Use the **Raw** URL, not the Gist page.                                                                |
| `https://api.n8n.io/api/workflows/templates/<id>`                       | One workflow from n8n's public template library — the endpoint n8n's own **Import from URL** uses.                            |
| `https://api.n8n.io/api/templates/workflows/<id>`                       | The same template with its listing metadata around it.                                                                        |
| `https://<host>/api/v1/workflows`                                       | A saved response from an n8n instance. Prefer `n8nBaseUrl` for a live one — it paginates and unlocks the instance-only rules. |

A URL that returns several workflows — an `n8n export:workflow --all --output` bundle, or a `{ "workflows": [...] }` array — is fine too; each one is audited and billed separately. A URL that fetches but contains no workflow is logged and skipped rather than failing the run.

The three sources are additive. If the same workflow arrives from more than one, it is audited **once** — the instance copy wins over a URL, which wins over pasted JSON — and every skipped duplicate is named in the run log. You are never billed twice for one workflow.

#### Auditing a live instance

Create the API key under **Settings → n8n API**; it needs the `workflow:list` and `workflow:read` scopes. The public API is a paid n8n feature and is unavailable during the free trial.

`n8nApiKey` is marked secret: stored encrypted, redacted from the run log, and never written to a dataset.

### Output

#### Findings — one row per issue

**Default dataset**, most severe first:

```json
{
    "fingerprint": "8db3cb38c79e",
    "workflowId": "customer-intake",
    "workflowName": "Customer intake",
    "workflowSource": "json",
    "scope": "node",
    "nodeId": "3",
    "nodeName": "Enrich",
    "nodeType": "n8n-nodes-base.httpRequest",
    "nodeTypeVersion": 3,
    "nodeDisabled": false,
    "rule": "secret-in-parameters",
    "ruleTitle": "Credential hardcoded in node parameters",
    "category": "secrets",
    "severity": "critical",
    "severityRank": 4,
    "message": "\"headerParameters.parameters[0].value\" on \"Enrich\" holds what looks like an OpenAI API key.",
    "remediation": "Move the value into an n8n credential and reference it from the node…",
    "evidence": "Bear…<redacted, 63 chars>",
    "parameterPath": "headerParameters.parameters[0].value",
    "docsUrl": null,
    "auditedAt": "2026-08-31T10:13:50.621Z"
}
```

- **`fingerprint`** is a stable id for the finding, built from the workflow, the rule, the node and the parameter — not from the message or the evidence. Diff two runs on this field to see only what changed.
- **`severityRank`** is `severity` as a number, 4 down to 0. Sort on it rather than on `severity`, whose names sort alphabetically.
- **`scope`** is `node` or `workflow`. Three rules report against the workflow as a whole — no error handling, no error workflow, no trigger — and their node fields are all null.
- **`nodeDisabled`** marks a finding against a node that is switched off.

#### Workflow scores — one row per workflow

**`summaries` dataset**, with a health score out of 100, node and credential counts, and counts by severity. Read its **Workflow scores** view first on a multi-workflow run to see which workflow to open in the findings table.

`credentialCount` and `credentialNames` answer "what does this workflow have access to?" — names only, never a secret and never the credential id.

Every row carries the `runId` that produced it, along with the `ruleSet` and `minSeverity` the run used. This table is retained across runs, so check those two before comparing scores: a run narrowed to `critical` scores higher than a full one on the same workflow.

#### Run totals

**Key-value store — `summary-run`**: workflows audited, skipped and deduplicated; average score; findings by severity and by rule; the rule set and severity floor; whether the node index came from n8n live or from the bundled snapshot; any rule that failed; any warning the input raised; `reportRequested`, `reportGenerated` and `reportUrl`; and `instanceError` if the n8n instance could not be read.

#### HTML report — optional

Switch on **HTML audit report** to get `report.html` in the key-value store: the whole run as one page, every workflow's score followed by the findings grouped by severity. It appears as **Audit report (HTML)** on the run's **Output** tab, and its link is also on the run summary as `reportUrl` and in the run log.

It is **billed as its own event**, once per run, on top of the per-workflow charge, so it is off unless you ask for it. A run that leaves it off writes no report at all; every finding and every score still lands in the datasets.

#### How the score works

A workflow starts at 100 and loses points for each finding, weighted by severity:

| Severity | Points off |
| -------- | ---------- |
| critical | 30         |
| high     | 15         |
| medium   | 6          |
| low      | 2          |
| info     | 0          |

100 means nothing above `info` was found, and 0 is the floor. `info` findings never cost anything, and **no single rule can deduct more than 45 points** however many times it fires. Use the score to rank workflows against each other and to track one over time; for the precise picture, read the finding count and severity breakdown next to it.

#### Evidence is always masked

Every value that could be a credential is reduced to a short prefix and its length (`sk-p…<redacted, 51 chars>`) before it reaches the output — enough to find the key in your workflow, never enough to use it.

### Pricing

The Actor is **pay per event**, and there are two events:

| Event              | Charged                                                     | When                                         |
| ------------------ | ----------------------------------------------------------- | -------------------------------------------- |
| `workflow-audited` | Once per workflow                                           | After that workflow's findings are written   |
| `report-generated` | Once per run, only if you switched on **HTML audit report** | After the report reaches the key-value store |

The cost of a run is the number of workflows in it, plus one if you asked for the report: auditing one pasted workflow is one charge; sweeping an instance of 40 is 40. Current per-event prices are on this Actor's Store page.

### Running it from n8n

Install the official [Apify node](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.apify/), add a **Run Actor** step, and pass the workflow JSON as input. Paired with a Schedule Trigger, that gives you a recurring audit of an entire instance — with results landing back in n8n through the **Actor Run Finished** trigger.

### Calling it from the API

A single audit takes a few seconds, so the Actor can run synchronously — one request in, findings out, no polling:

```bash
curl -X POST "https://api.apify.com/v2/acts/mediocre_interest~n8n-workflow-auditor/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
        "workflowJson": {
          "name": "Incoming leads",
          "nodes": [
            { "name": "Webhook", "type": "n8n-nodes-base.webhook", "typeVersion": 2,
              "position": [0, 0], "parameters": { "path": "incoming" } }
          ],
          "connections": {}
        },
        "minSeverity": "medium"
      }'
```

The response body is a JSON array of the finding rows shown under [Output](#output). Add `&format=csv` to get a spreadsheet instead, or `&fields=severity,rule,nodeName,message` to trim the columns.

For a longer sweep of a whole instance, start the run asynchronously with `POST /v2/acts/.../runs` and read the dataset when the run finishes, or let the [Apify node inside n8n](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.apify/) do both for you.

For a CI gate built on this endpoint, see [Using this as a CI gate](#using-this-as-a-ci-gate).

### Using this as a CI gate

Every finding comes from a deterministic rule, so a build that passes today passes tomorrow on the same input — there is no model behind it to drift, and no run-to-run variance to chase.

Call the [sync endpoint](#calling-it-from-the-api) on every pull request with the changed workflow's JSON, and fail the build if anything comes back `critical`. `$WORKFLOW_FILE` below is the workflow JSON exported for the pull request; `$APIFY_TOKEN` is your Apify API token:

```bash
RESULT=$(curl -s -X POST "https://api.apify.com/v2/acts/mediocre_interest~n8n-workflow-auditor/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d "$(jq -n --slurpfile wf "$WORKFLOW_FILE" '{workflowJson: $wf[0]}')")

if echo "$RESULT" | jq -e 'any(.[]; .severity == "critical")' > /dev/null; then
  echo "$RESULT" | jq '[.[] | select(.severity == "critical") | {rule, nodeName, message}]'
  exit 1
fi
```

To fail only on **new** findings instead of every pre-existing `critical` — useful once a workflow already carries findings the team has accepted — cache the previous run's `fingerprint` values and gate on any that are not in that cache:

```bash
NEW=$(comm -13 <(sort previous-fingerprints.txt) <(echo "$RESULT" | jq -r '.[].fingerprint' | sort))
if [ -n "$NEW" ]; then
  echo "New finding(s) since the last run: $NEW"
  exit 1
fi
echo "$RESULT" | jq -r '.[].fingerprint' | sort > previous-fingerprints.txt
```

For a scheduled sweep of a whole instance instead of a per-PR check, use Apify's own scheduler to point the Actor at your instance — see [Auditing a live instance](#auditing-a-live-instance).

### FAQ

#### Does this send my workflows to an LLM?

No. Every finding comes from a deterministic rule, which is why the same workflow produces identical findings on every run.

#### Can it see my credentials?

No. n8n's public API returns per-node credentials as `{ id, name }` references with the secret values stripped, so they never reach the Actor. Your `n8nApiKey` is stored encrypted, redacted from the run log, and never written to a dataset. Evidence for a key found hardcoded in a parameter is masked to a prefix and a length before it reaches the output.

#### Does it change my workflows?

No. The Actor only ever reads. Against an instance it calls `GET /api/v1/workflows` and nothing else.

#### How is this different from n8n's built-in `n8n audit`?

n8n's audit is instance-scoped, needs owner credentials, and cannot read a JSON file, so it cannot run in CI or across a portfolio of client exports. It covers five categories; this Actor covers twenty rules across six, adding hardcoded secrets, error handling, `typeVersion` staleness, graph reachability, HTTP hygiene, and the Form-node expression-injection CVE. Where the two overlap, this Actor mirrors n8n's own definitions so the verdicts agree.

#### Why did the run finish with no findings?

Three possibilities. Your **minimum severity** is above anything the run could report — `reliability` has no rule more severe than `medium` and `maintainability` none above `high`, so pairing either with `high` or `critical` filters out everything, and the run log warns you when that happens. Or your **ignore rules** cover what was found. Or the workflow really is clean, in which case the `summaries` row records a score of 100.

#### Can I run it in CI or on a schedule?

Yes — see [Using this as a CI gate](#using-this-as-a-ci-gate) for CI. On a schedule, use Apify's scheduler to point the Actor at your instance; the `summaries` table keeps a row per workflow per run, so a score moving down is a regression you can act on.

#### What happens if n8n's API is down?

The audit still runs and its verdicts do not change. Deprecation and version rules use n8n's node index, which the Actor fetches fresh at the start of every run and otherwise falls back to a bundled snapshot of all 572 built-in nodes. The run log says which one was used.

#### I switched on the report but the Output tab shows nothing

The findings and scores are already in the datasets by the time the run finishes — the report can take a little longer to reach the key-value store. Refresh the run's page in Console. If it is still missing after that, check `reportGenerated` and `reportUrl` in the run summary to confirm whether it was written at all.

### What other Actors work with this one?

| Actor                                                                                                   | What it does                                                                                                                                             |
| ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [n8n Node Catalog & Community Package Scraper](https://apify.com/mediocre_interest/n8n-node-catalog)    | Catalogs every n8n node — built-in, verified, and community — with npm provenance, license, weekly downloads, and maintenance risk for each package.     |
| [Ad Library Scraper — Google, Meta & LinkedIn](https://apify.com/mediocre_interest/ads-library-scraper) | Scrapes ads from the Google Ads Transparency Center, Meta Ad Library and LinkedIn Ad Library in one run — ad copy, creatives, impressions and run dates. |
| [Multi-Platform Job Scraper](https://apify.com/mediocre_interest/multi-platform-jobs-scraper)           | Collects job listings from LinkedIn, Indeed, Glassdoor, ZipRecruiter, Greenhouse, Lever and more into a single dataset.                                  |

The node catalog above is a natural companion if you also want an inventory of every node in play across your instance. The other two are the kind of Actor an n8n workflow calls on a schedule through the [Apify node](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.apify/) — and this one audits the workflow doing the calling.

### Support

Found a false positive, a rule that should exist, or a workflow shape the parser mishandles? Open an issue on the Actor's **Issues** tab in Apify Console.

When reporting a finding you disagree with, include the `rule` ID from the row and the smallest workflow JSON that reproduces it.

# Actor input Schema

## `workflowJson` (type: `object`):

Paste one exported n8n workflow. In n8n use Workflow menu > Download, or select the nodes on the canvas and press Ctrl+C. To audit several at once, paste them wrapped as `{"workflows": [ ... ]}` - an `n8n export:workflow` bundle or a raw public-API response already has that shape. For many workflows, use Workflow JSON URLs or an n8n instance connection instead.

## `workflowUrls` (type: `array`):

Fetch exported workflow JSON from these URLs - a raw Gist, a file in a Git repo, or any public link. A URL that returns several workflows is audited as several workflows.

## `n8nBaseUrl` (type: `string`):

The base URL of your n8n instance, for example `https://n8n.example.com`. The `/api/v1` suffix is added automatically if you leave it off.

## `n8nApiKey` (type: `string`):

An n8n public API key, created under Settings > n8n API. Needs the `workflow:list` and `workflow:read` scopes. Stored encrypted, never written to the dataset, and redacted from the run log.

## `workflowIds` (type: `array`):

Audit only these workflow IDs. Leave empty to audit every workflow on the instance.

## `activeOnly` (type: `boolean`):

Skip deactivated workflows, so the audit covers only what is running. Turning it on is also the simplest way to control what an instance sweep costs, since every workflow audited is billed - drafts and retired workflows are skipped. Ignored when Workflow IDs is set.

## `ruleSet` (type: `string`):

`security` covers hardcoded credentials, unauthenticated webhooks, expression injection, and SQL interpolation. `reliability` covers error handling, timeouts, loops, and unreachable nodes. `maintainability` covers deprecated nodes, stale type versions, and community-node supply chain.

## `minSeverity` (type: `string`):

Findings below this level are not reported. Raise it to `medium` for a shorter report; drop it to `info` to include advisory findings such as missing pagination.

## `ignoreRules` (type: `array`):

Rule IDs to suppress, for example `http-no-timeout` or `stale-type-version`. Every finding row carries its rule ID, so you can copy one from a previous run.

## `includeReport` (type: `boolean`):

Build a shareable HTML page for this run - every workflow's score, then the findings grouped by severity - and link it from the run's Output tab. **Billed as its own event, once per run, on top of the per-workflow charge.** Leave it off and you still get every finding and every score in the datasets; only the page is skipped.

## Actor input object example

```json
{
  "workflowJson": {
    "name": "Example",
    "nodes": [
      {
        "name": "Webhook",
        "type": "n8n-nodes-base.webhook",
        "typeVersion": 2,
        "position": [
          0,
          0
        ],
        "parameters": {
          "path": "incoming"
        }
      }
    ],
    "connections": {}
  },
  "workflowUrls": [],
  "workflowIds": [],
  "activeOnly": false,
  "ruleSet": "all",
  "minSeverity": "low",
  "ignoreRules": [],
  "includeReport": false
}
```

# Actor output Schema

## `findings` (type: `string`):

No description

## `workflowScores` (type: `string`):

No description

## `runSummary` (type: `string`):

No description

## `report` (type: `string`):

The whole run as one readable page. Produced only when "HTML audit report" is switched on in the input; a run that leaves it off has nothing behind this link. Its URL is also on the run summary as reportUrl.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "workflowJson": {
        "name": "Example",
        "nodes": [
            {
                "name": "Webhook",
                "type": "n8n-nodes-base.webhook",
                "typeVersion": 2,
                "position": [
                    0,
                    0
                ],
                "parameters": {
                    "path": "incoming"
                }
            }
        ],
        "connections": {}
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("mediocre_interest/n8n-workflow-auditor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "workflowJson": {
        "name": "Example",
        "nodes": [{
                "name": "Webhook",
                "type": "n8n-nodes-base.webhook",
                "typeVersion": 2,
                "position": [
                    0,
                    0,
                ],
                "parameters": { "path": "incoming" },
            }],
        "connections": {},
    } }

# Run the Actor and wait for it to finish
run = client.actor("mediocre_interest/n8n-workflow-auditor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "workflowJson": {
    "name": "Example",
    "nodes": [
      {
        "name": "Webhook",
        "type": "n8n-nodes-base.webhook",
        "typeVersion": 2,
        "position": [
          0,
          0
        ],
        "parameters": {
          "path": "incoming"
        }
      }
    ],
    "connections": {}
  }
}' |
apify call mediocre_interest/n8n-workflow-auditor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mediocre_interest/n8n-workflow-auditor"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/ckl15Ixct77xV2yQE/builds/cA6KkLnoaYhdTUJfa/openapi.json
