# n8n 3.0 Migration Checker, Workflow Audit and Fix (`edgef-4/n8n-3-migration-checker-fixer`) Actor

n8n migration checker, n8n workflow checker and JSON validator for the n8n 3.0 upgrade, no login. Mode check lists breaking changes, deprecated nodes and security advisories in exported workflows; explain writes an n8n workflow audit; fix, a workflow fixer powered by Claude, returns fixed JSON.

- **URL**: https://apify.com/edgef-4/n8n-3-migration-checker-fixer.md
- **Developed by:** [Edge](https://apify.com/edgef-4) (community)
- **Categories:** Developer tools, AI, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 workflow checked for n8n 3.0s

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## n8n 3.0 Migration Checker, Workflow Audit and Fix

n8n migration checker, n8n workflow checker and JSON validator for the n8n 3.0 upgrade, no login. Mode check lists
breaking changes, deprecated nodes and security advisories in exported workflows; explain writes an n8n workflow
audit; fix, a workflow fixer powered by Claude, returns fixed JSON. Three modes:

- **check (default): 0.01 USD per workflow checked.** Lists what n8n 3.0 breaks in each workflow (rule, level,
  node, the replacement, the source link) with a readiness verdict. No AI, no API key, results in seconds.
- **fix: 2.00 USD per fixed workflow.** Also rewrites what breaks and returns the fixed workflow JSON with a
  change report (node, before, after, rule, source). Free when a workflow is already ready, needs only human
  decisions, or the AI cannot fix every finding it may fix (then no fixed JSON is returned).
- **explain: 0.05 USD per workflow explained.** A plain-English audit of each workflow: what it does, a node
  table, credential types, outside hosts, risks (n8n 3.0, security advisories, hardcoded secrets shown masked,
  missing error handling) and a 0 to 100 health score with the top 3 fixes, plus one printable Markdown report per
  run. No AI, no API key.

### Use n8n's own report when you can log in

n8n ships a free Migration report inside the app (Settings > Migration report), and on a live instance it is the
final word. This Actor is for what that report cannot reach: exported files with no login, for example a
client's export, a template library, a backup, a check before import, or an AI agent working on files.

Of the 23 rules in n8n's Migration Report, 16 are covered by the checker behind this Actor (3 of them only in
part) and 7 need a live instance (instance settings such as the binary data mode or environment variables). One
of the 16, Docker-only installs, reads the server itself, so from an export this Actor covers 15.

### For AI agents

The Actor is agent-payable: pay per event, no subscription. Send workflows with `mode` `check` to learn what
breaks, `explain` for a plain-English audit, or `fix` to get them rewritten. Read `verdict` and `findings` (check),
`summary`, `risks` and `topFixes` (explain), or take `fixedWorkflow` when `status` is `fixed` and show `needsHuman`
to your user (fix). Set a maximum charge per run to cap spend.

1. HTTP, check mode, one call that waits for the result (`input.json` holds
   `{"mode": "check", "workflows": [ ...exported workflows... ]}`):

```bash
curl -s -X POST "https://api.apify.com/v2/acts/<username>~n8n-3-migration-checker-fixer/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" -H "Content-Type: application/json" --data @input.json
```

2. Apify MCP server (https://mcp.apify.com), tool `call-actor`, fix mode:

```json
{ "actor": "<username>/n8n-3-migration-checker-fixer",
  "input": { "mode": "fix", "workflows": [ { "name": "My workflow", "nodes": [], "connections": {} } ] } }
```

Then read the run's dataset items with `get-dataset-items`.

3. Python with apify-client: check everything, then fix only what fix mode can rewrite:

```python
import json, os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
actor = client.actor("<username>/n8n-3-migration-checker-fixer")
workflows = [json.load(open(p)) for p in ["a.json", "b.json"]]
run = actor.call(run_input={"mode": "check", "workflows": workflows})
checked = list(client.dataset(run["defaultDatasetId"]).iterate_items())
todo = [workflows[i["workflowIndex"]] for i in checked
        if i["verdict"] == "not_ready" and any(f["autoFixable"] for f in i["findings"])]
if todo:
    run = actor.call(run_input={"mode": "fix", "workflows": todo})
    for item in client.dataset(run["defaultDatasetId"]).iterate_items():
        print(item["workflowName"], item["status"], item["message"])
```

### What it finds and fixes

Check mode reports every row below with its replacement and source. Fix mode does what the right column says.

| n8n 3.0 breaking change | What mode fix does |
|---|---|
| Removed nodes (37 types): Function, Function Item, Cron, Interval, Item Lists, AI Transform, legacy OpenAI and more | replaces each node in place with the node n8n names (Code, Schedule Trigger, Remove Duplicates and so on), settings carried over |
| AI Agent version 1 and the old agent modes | moves the node to the current Tools Agent version, prompt and options kept |
| `$evaluateExpression()` in a Code node, the `$getPairedItem` helper | rewrites them when the meaning is certain |
| Sub-workflow from a local file or URL, Edit Image version 1, Always Output Data on If or Switch, Gmail Trigger below 1.4 | lists them under "needs a human" with exactly what to do (free when nothing else needs fixing) |
| Task runner 60 s timeout, larger SSRF block list, Compression limits, community nodes, Chat Trigger JSON frames | notes only: nothing to change in the JSON, check them on your instance |

Source of every rule: n8n's own page, https://docs.n8n.io/changelog/v30-breaking-changes

### How it works

1. A deterministic n8n 3.0 checker (14 rules) reads each workflow. In mode check that is the whole job.
2. Mode fix, nothing breaks: "already n8n 3.0 ready", free. Only human decisions left: "needs a human", free.
3. Mode fix, something breaks: the n8n 3.0 fixer agent, Powered by Claude, rewrites only the flagged nodes in a
   sealed work folder. It cannot browse the web, run commands or touch anything else.
4. The checker runs again, plus a guard: same node ids, names and positions, same connections, same credentials,
   same webhook ids and paths, only known n8n node types, versions and parameters. You pay only when the result
   passes the guard and every finding the AI may fix is gone (findings left only on nodes held for a human, listed
   under "needs a human"). Only a paid result returns the fixed JSON and its change list.

### Safety

- Never changes credentials, webhook paths or node ids; never adds, removes or rewires nodes.
- Credentials stay referenced by id: an export never holds their values.
- Mode fix sends the workflow to Anthropic (Claude) to rewrite it, including any value hardcoded in a node (a
  token in a header, a URL, code). Pinned execution data (`pinData`) and trigger state (`staticData`) are removed
  first and put back unchanged; the item says so in `withheldFromAi`. Modes check and explain send nothing anywhere.
- Every change in a returned workflow is listed: node, field, before, after, rule and source link.
- Anything it must not guess (for example code it cannot translate with certainty) goes to "needs a human" with
  the reason; when the AI leaves such a node, that workflow is free.

### Explain mode: plain-English audit

Mode explain is the first step of an n8n audit: **0.05 USD per workflow explained.** Fixed rules, no AI and no API
key, so the same export always gives the same report. One dataset item per workflow:

| field | what it holds |
|---|---|
| `summary` | what the workflow does in 3 to 5 plain sentences: trigger, main steps, last steps, outside calls, health |
| `nodes` | node table: `name`, `type` and `purpose` in plain words; disabled nodes and sticky notes are marked |
| `credentials` | credential type names (for example `slackApi`) and the nodes that use them; never a credential id, name or value |
| `apps`, `hosts` | outside services the app nodes call, and hosts named in URL parameters and code (never a path or query) |
| `triggers` | how it starts: a schedule in words with its time zone, a webhook method and path, chat, form, by hand |
| `risks` | `kind`, `severity`, `points`, `nodes`, `text`, `fix`, `source`; a hardcoded secret adds `field` and `masked` |
| `healthScore`, `topFixes` | 0 to 100, and the fixes of the risks with the most points (at most 3) |
| `verdict`, `findings`, `advisories` | the same as mode check |

The risks it looks for, and what each one costs the health score (100 minus all points, never below 0):

| risk | severity | points |
|---|---|---|
| `hardcoded_secret`: a token, key or password written into a node (header, query, body, URL or code), shown masked: at most its first 4 characters, then \*\*\*\*\*\*\*\* | high | 20 each |
| `advisory`: the given `n8nVersion` is affected by n8n security advisories of 28 Oct 2026 (one risk: upgrade to the first version that fixes them all) | high if one of them is high, else medium | 20 or 10 |
| `n8n_3_breaking`: a node that breaks on n8n 3.0, as in mode check | medium | 10 per node |
| `no_error_workflow`: no error workflow is set, so a failed run alerts nobody | medium | 10 |
| `advisory_check_version`: advisories name nodes of the workflow and no `n8nVersion` was given | low | 3 |
| `no_retry`: steps that call an outside service with no Retry On Fail and no error output | low | 3 |
| `open_webhook`: a webhook with no authentication | low | 3 each |
| `n8n_3_note`: n8n 3.0 notes to check on the instance | info | 0 |

Every run also stores one printable Markdown report in its key-value store under the key `REPORT.md`: an overview
table, then one section per workflow (what it does, how it starts, nodes, credential types, services and hosts,
risks, advisories, top fixes). Open it from the run's Storage tab, or download
`https://api.apify.com/v2/key-value-stores/<storeId>/records/REPORT.md`.

Example input (up to 200 workflows per run; the full file is `examples/explain_input.json`):

```json
{ "mode": "explain", "n8nVersion": "2.44.6",
  "workflows": [ { "name": "Signup alert to Slack", "nodes": [], "connections": {} } ] }
```

Summary of that workflow, as the Actor writes it: "It starts when an HTTP POST request reaches the webhook path
/new-signup (New signup). Then it sets or renames fields on each item (Format alert), then posts a message to Slack
(Post to #signups). Last, it sends the reply to the webhook caller (Reply ok). It calls Slack, and it uses 1 stored
credential type (slackApi). Health score: 64 of 100 (4 risks found); n8n 3.0: ready."

Free: invalid input and skipped items. Explain mode reads only the export: node purposes come from a fixed table of
common nodes (other app nodes read "works with <app>, operation ..."), and secrets are found by pattern, so a
secret in an unusual format can be missed and a long random value in a field named like a secret can be flagged.

### Input

```json
{ "mode": "check", "workflows": [ { "name": "My workflow", "nodes": [], "connections": {} } ] }
```

- `mode`: `check` (default), `explain` or `fix`.
- `workflows`: exported n8n workflow objects (Download in the n8n editor, or `n8n export:workflow`). Mode check:
  up to 500 per run. Mode explain: up to 200 per run. Mode fix: up to 20 per run, 150 KB each. The example input
  is a small sample workflow that is already n8n 3.0 ready: mode check returns it in seconds, no AI, no key.
- `n8nVersion` (optional, empty by default, modes check and explain): the n8n version that runs these workflows,
  for example `2.44.6`. See "Security advisories (modes check and explain)" below.

### Output (one dataset item per workflow)

The Output tab has four views: Overview, Check (breaking changes and security advisories), Explain (n8n workflow
audit) and Fix (fixed workflow JSON). Mode explain also links its Markdown report, `REPORT.md`.

| field | meaning |
|---|---|
| `mode`, `status` | `check`: `checked`; `explain`: `explained`; `fix`: `fixed`, `already_ready`, `needs_human`, `partial`; all modes: `invalid_input`, `skipped`, `error` |
| `charged` | check and explain: true for every workflow that parsed; fix: true only for `fixed` |
| `verdict` | `ready`, `ready_with_notes` (info only) or `not_ready`, for the workflow as sent (fix: only on charged items) |
| `findings` | every finding: `rule`, `level` (fix or info), `node`, `nodeType`, `text`, `replacement`, `source`, `autoFixable` (fix: only on charged items; a free fix item points to mode check) |
| `advisories` | check and explain: n8n security advisories the workflow or the given version touches: `id`, `severity`, `title`, `nodes`, `fixedIn`, `status` (`affected`, `fixed`, `check version` or `dependency notice`), `link`, and for a dependency notice its `notice` |
| `summary`, `nodes`, `credentials`, `apps`, `hosts`, `triggers`, `risks`, `healthScore`, `topFixes` | explain: see "Explain mode" above |
| `fixedWorkflow` | fix: the fixed workflow JSON, ready to import into n8n 3.0 (only when `charged`) |
| `changes` | fix: every change: `node`, `field`, `before`, `after`, `rule`, `source` |
| `needsHuman` | fix: what only you can decide: `node`, `rule`, `reason`, `source` |
| `notes`, `remaining`, `reasons` | fix: info findings after the fix and fix-level findings still open (both on charged items), why a workflow was not fixed or not charged |

### Security advisories (modes check and explain)

On 28 Oct 2026 n8n published 12 security advisories. Modes check and explain list the ones each workflow
touches in `advisories`, next to the 3.0 findings.

- It reads only the exported file you send: node types, node names, and whether a node has stored sign-in data.
  It never logs in to your n8n and never reads a sign-in value.
- A node of a listed type in the workflow (Edit Image, Function, Function Item, LangChain Code, NocoDB, MongoDB,
  Chat Trigger, or any node with stored sign-in data) lists the advisory with those node names.
- With `n8nVersion` (for example `2.44.6`) each entry says `affected` or `fixed` for that version; without it,
  `check version`. A fix on your version's own line (for example 2.45.x) decides; otherwise a fix on an older line
  of the same major version means fixed.
- Advisories about the whole n8n instance, and two whose node type no public n8n page names (Vector Store
  (OracleDB), Asana Trigger), appear only when you give a version and that version is affected.
- Advisories never change the 3.0 verdict or the price: still one 0.01 USD event per workflow checked (mode
  explain counts affected advisories in the health score).

| Advisory | Severity | Shown by | Fixed in |
|---|---|---|---|
| [GHSA-gx3v-3x3v-f8r5](https://github.com/n8n-io/n8n/security/advisories/GHSA-gx3v-3x3v-f8r5) | high | version (workflow expression isolation) | 1.123.89, 2.45.5, 2.46.1, 3.0.1 |
| [GHSA-f2cw-9483-7vcp](https://github.com/n8n-io/n8n/security/advisories/GHSA-f2cw-9483-7vcp) | high | Edit Image node | 1.123.89, 2.45.5, 2.46.1, 3.0.1 |
| [GHSA-9p7v-45m2-wxgj](https://github.com/n8n-io/n8n/security/advisories/GHSA-9p7v-45m2-wxgj) | high | Function, Function Item, LangChain Code nodes | 2.42.6, 2.43.3, 2.44.0, 3.0.1 |
| [GHSA-jmcg-c7p5-q69g](https://github.com/n8n-io/n8n/security/advisories/GHSA-jmcg-c7p5-q69g) | moderate | NocoDB node | 1.123.89, 2.45.5, 2.46.1, 3.0.1 |
| [GHSA-prmc-fg87-r4gh](https://github.com/n8n-io/n8n/security/advisories/GHSA-prmc-fg87-r4gh) | moderate | any node with stored sign-in data | 2.45.5, 2.46.1, 3.0.1 |
| [GHSA-2x68-96jw-5r6c](https://github.com/n8n-io/n8n/security/advisories/GHSA-2x68-96jw-5r6c) | moderate | version (Vector Store (OracleDB) node) | 2.43.5, 2.44.1, 3.0.1 |
| [GHSA-mx4r-96jx-v278](https://github.com/n8n-io/n8n/security/advisories/GHSA-mx4r-96jx-v278) | moderate | version (Asana Trigger node) | 2.38.0, 3.0.1 |
| [GHSA-rc3w-8jc8-7x3w](https://github.com/n8n-io/n8n/security/advisories/GHSA-rc3w-8jc8-7x3w) | moderate | version (MCP OAuth client registration) | 1.123.89, 2.45.5, 2.46.1, 3.0.1 |
| [GHSA-426f-xmcv-g8pg](https://github.com/n8n-io/n8n/security/advisories/GHSA-426f-xmcv-g8pg) | moderate | version (end-user credential connect flow) | 2.45.5, 2.46.1, 3.0.1 |
| [GHSA-4v22-g448-h4rg](https://github.com/n8n-io/n8n/security/advisories/GHSA-4v22-g448-h4rg) | moderate | MongoDB node | 1.123.89, 2.45.5, 2.46.1, 3.0.1 |
| [GHSA-pwj5-wwm6-g83j](https://github.com/n8n-io/n8n/security/advisories/GHSA-pwj5-wwm6-g83j) | moderate | Chat Trigger node | 1.123.89, 2.45.5, 2.46.1, 3.0.1 |
| [GHSA-9qx8-fhxv-w794](https://github.com/n8n-io/n8n/security/advisories/GHSA-9qx8-fhxv-w794) | moderate | version (Browser Use feature) | 2.45.5, 2.46.1, 3.0.1 |

This list is dated: the advisories published on 28 Oct 2026, read on 29 Oct 2026. When n8n publishes new ones at
https://github.com/n8n-io/n8n/security/advisories, the list needs a re-check before you rely on it.

#### MCP dependency notices

n8n bundles the MCP TypeScript SDK (`@modelcontextprotocol/sdk`). A workflow with an MCP node (MCP Server Trigger,
MCP Client, MCP Client Tool, MCP Registry Client) lists the 4 SDK advisories of 20 Oct 2026 with those node names,
`status` `dependency notice` and this `notice`, whatever `n8nVersion` says:

> n8n bundles @modelcontextprotocol/sdk 1.31.0 (stable 2.45.7 and beta 2.46.3; every n8n 2.x release on npm bundles a version below 1.32.0, checked on 1 Nov 2026; on n8n 1.x it depends on the version and the install); this SDK advisory is fixed in 1.32.0; whether your workflow is exposed depends on use (an MCP endpoint reachable from outside, OAuth redirects). Fix: keep MCP endpoints off public ports until an n8n release bundles SDK 1.32.0 or later.

- [GHSA-46jr-4wx8-v453](https://github.com/advisories/GHSA-46jr-4wx8-v453), high: one HTTP request could exhaust server memory during validation
- [GHSA-22jm-h49p-29qw](https://github.com/advisories/GHSA-22jm-h49p-29qw), high: experimental tasks were not tied to the session that created them
- [GHSA-rvq5-wwqv-78pq](https://github.com/advisories/GHSA-rvq5-wwqv-78pq), moderate: server bearer authentication accepted tokens issued for another service
- [GHSA-6prh-2h8m-c8cw](https://github.com/advisories/GHSA-6prh-2h8m-c8cw), moderate: client transports and OAuth requests followed cross-origin redirects

A notice makes no claim that your n8n is vulnerable, and it never changes the 3.0 verdict, the health score or the
price. Checked on 1 Nov 2026: when an n8n release bundles SDK 1.32.0 or later, the notice needs a re-check.

### Limits

- Fix mode changes nodes in place: it never adds nodes or rewires a workflow. A fix that needs that is listed
  under "needs a human".
- Instance settings are outside an export (Docker-only installs, binary data mode, environment variables).
  n8n's own Settings > Migration report on your instance is the final word.

# Actor input Schema

## `mode` (type: `string`):

check (default): the n8n migration checker and JSON validator lists the n8n 3.0 breaking changes in each workflow, deprecated and removed nodes among them, with the replacement and the source, plus the n8n security advisories it touches; no AI, no key. explain: an n8n workflow audit in plain English (what it does, a node table, credential types, outside hosts, risks, a 0 to 100 health score with the top 3 fixes) and one Markdown report per run; no AI, no key. fix: the workflow fixer (AI, powered by Claude) also rewrites what breaks and is charged only for a workflow that comes back with zero fix-level findings.

## `workflows` (type: `array`):

A list of exported n8n workflow JSON objects, each with nodes and connections (Download in the n8n editor, or n8n export:workflow). Mode check: up to 500 per run; mode explain: up to 200; mode fix: up to 20, 150 KB each. Anything that is not an exported workflow comes back as invalid_input, free. The example is a small sample workflow that is already n8n 3.0 ready, so the example run (mode check, no AI, no key) finishes in seconds: replace it with your own workflows.

## `n8nVersion` (type: `string`):

The n8n version that runs these workflows, for example 2.44.6. With it, each n8n security advisory a workflow touches says affected or fixed, and advisories about the whole n8n instance are listed when that version is affected. Empty (the default): the advisories a workflow touches say check version. Modes check and explain only; it never changes the price or the n8n 3.0 verdict (mode explain counts affected advisories in the health score).

## Actor input object example

```json
{
  "mode": "check",
  "workflows": [
    {
      "name": "Signup webhook (already 3.0 ready)",
      "nodes": [
        {
          "parameters": {
            "httpMethod": "POST",
            "path": "signup-hook",
            "responseMode": "responseNode",
            "options": {}
          },
          "id": "88d9e0f1-a2b3-4c4d-9e6f-7a8b9c0d1e32",
          "name": "Signup webhook",
          "type": "n8n-nodes-base.webhook",
          "typeVersion": 2,
          "position": [
            0,
            0
          ],
          "webhookId": "9e0f1a2b-3c4d-4e5f-8a7b-8c9d0e1f2a43"
        },
        {
          "parameters": {
            "jsCode": "return $input.all().map(item => ({ json: { email: item.json.body.email.toLowerCase() } }));"
          },
          "id": "99e0f1a2-b3c4-4d5e-8f7a-8b9c0d1e2f54",
          "name": "Normalize email",
          "type": "n8n-nodes-base.code",
          "typeVersion": 2,
          "position": [
            220,
            0
          ]
        }
      ],
      "connections": {
        "Signup webhook": {
          "main": [
            [
              {
                "node": "Normalize email",
                "type": "main",
                "index": 0
              }
            ]
          ]
        }
      }
    }
  ],
  "n8nVersion": ""
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset items, Overview view selected; the Check, Explain and Fix views show each mode's columns.

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

Mode explain only: the run's printable n8n workflow audit, key REPORT.md in the default key-value store. Modes check and fix write no report.

# 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 = {
    "workflows": [
        {
            "name": "Signup webhook (already 3.0 ready)",
            "nodes": [
                {
                    "parameters": {
                        "httpMethod": "POST",
                        "path": "signup-hook",
                        "responseMode": "responseNode",
                        "options": {}
                    },
                    "id": "88d9e0f1-a2b3-4c4d-9e6f-7a8b9c0d1e32",
                    "name": "Signup webhook",
                    "type": "n8n-nodes-base.webhook",
                    "typeVersion": 2,
                    "position": [
                        0,
                        0
                    ],
                    "webhookId": "9e0f1a2b-3c4d-4e5f-8a7b-8c9d0e1f2a43"
                },
                {
                    "parameters": {
                        "jsCode": "return $input.all().map(item => ({ json: { email: item.json.body.email.toLowerCase() } }));"
                    },
                    "id": "99e0f1a2-b3c4-4d5e-8f7a-8b9c0d1e2f54",
                    "name": "Normalize email",
                    "type": "n8n-nodes-base.code",
                    "typeVersion": 2,
                    "position": [
                        220,
                        0
                    ]
                }
            ],
            "connections": {
                "Signup webhook": {
                    "main": [
                        [
                            {
                                "node": "Normalize email",
                                "type": "main",
                                "index": 0
                            }
                        ]
                    ]
                }
            }
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("edgef-4/n8n-3-migration-checker-fixer").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 = { "workflows": [{
            "name": "Signup webhook (already 3.0 ready)",
            "nodes": [
                {
                    "parameters": {
                        "httpMethod": "POST",
                        "path": "signup-hook",
                        "responseMode": "responseNode",
                        "options": {},
                    },
                    "id": "88d9e0f1-a2b3-4c4d-9e6f-7a8b9c0d1e32",
                    "name": "Signup webhook",
                    "type": "n8n-nodes-base.webhook",
                    "typeVersion": 2,
                    "position": [
                        0,
                        0,
                    ],
                    "webhookId": "9e0f1a2b-3c4d-4e5f-8a7b-8c9d0e1f2a43",
                },
                {
                    "parameters": { "jsCode": "return $input.all().map(item => ({ json: { email: item.json.body.email.toLowerCase() } }));" },
                    "id": "99e0f1a2-b3c4-4d5e-8f7a-8b9c0d1e2f54",
                    "name": "Normalize email",
                    "type": "n8n-nodes-base.code",
                    "typeVersion": 2,
                    "position": [
                        220,
                        0,
                    ],
                },
            ],
            "connections": { "Signup webhook": { "main": [[{
                                "node": "Normalize email",
                                "type": "main",
                                "index": 0,
                            }]] } },
        }] }

# Run the Actor and wait for it to finish
run = client.actor("edgef-4/n8n-3-migration-checker-fixer").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 '{
  "workflows": [
    {
      "name": "Signup webhook (already 3.0 ready)",
      "nodes": [
        {
          "parameters": {
            "httpMethod": "POST",
            "path": "signup-hook",
            "responseMode": "responseNode",
            "options": {}
          },
          "id": "88d9e0f1-a2b3-4c4d-9e6f-7a8b9c0d1e32",
          "name": "Signup webhook",
          "type": "n8n-nodes-base.webhook",
          "typeVersion": 2,
          "position": [
            0,
            0
          ],
          "webhookId": "9e0f1a2b-3c4d-4e5f-8a7b-8c9d0e1f2a43"
        },
        {
          "parameters": {
            "jsCode": "return $input.all().map(item => ({ json: { email: item.json.body.email.toLowerCase() } }));"
          },
          "id": "99e0f1a2-b3c4-4d5e-8f7a-8b9c0d1e2f54",
          "name": "Normalize email",
          "type": "n8n-nodes-base.code",
          "typeVersion": 2,
          "position": [
            220,
            0
          ]
        }
      ],
      "connections": {
        "Signup webhook": {
          "main": [
            [
              {
                "node": "Normalize email",
                "type": "main",
                "index": 0
              }
            ]
          ]
        }
      }
    }
  ]
}' |
apify call edgef-4/n8n-3-migration-checker-fixer --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,edgef-4/n8n-3-migration-checker-fixer"
        }
    }
}
```

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/fo5GbO3QSaefrh0ZP/builds/mgdGD0qD7fhcXAdIG/openapi.json
