← Back to blog

n8n API: Build a Workflow Inventory and Compare Local Snapshots

Use the n8n API to collect accessible workflows with cursor pagination, save a local ID-to-name inventory, and report added, missing and renamed entries.

A magnifier and two filing trays represent collecting and comparing an n8n API workflow inventory.

Checked against the cited sources on .

Goal and prerequisites for the n8n API inventory

This tutorial uses the n8n API to collect every returned workflow page and compare a local ID-to-name snapshot with an earlier one. You need API access, permission to create a key, and a local Python environment. The n8n API documentation lists Cloud Starter, Pro and Enterprise and all self-hosted editions as supporting API access; it excludes the free trial. This availability reflects the documentation reviewed, which does not identify a deployed release.

The result covers workflows accessible to the collecting account and key, rather than proving instance-wide completeness. It detects membership and naming differences, not workflow-definition edits, execution behavior or publication state. Pages are not established as a point-in-time snapshot: changes during collection can affect the result.

We think a small inventory is a useful starting point because its review question stays clear: which workflow IDs and names changed?

Sources: n8n-docs/docs/connect/n8n-api/api-reference.md at main · n8n-io/n8n-docs · GitHub, Workflow | Connect | n8n Docs

1. Prepare the key and API root

In Settings > n8n API, create a labeled key with an expiration. Enterprise supports scoped keys: select workflow:list for collection access. Non-Enterprise keys have full access to the account's resources and capabilities; restricting this script to GET does not make those credentials read-only.

Set N8N_API_ROOT in your local environment to your instance's HTTPS address followed by /api/v1. For Cloud, use your workspace's app.n8n.cloud host; for self-hosted deployments, use your instance host and preserve any deployment-specific base path. Set N8N_API_KEY separately. Keep the key out of snapshots and shared examples.

Sources: n8n-docs/docs/connect/n8n-api/authentication.md at main · n8n-io/n8n-docs · GitHub, Authentication | Connect | n8n Docs

2. Collect all pages and save the inventory

Workflow page bundles pass through a sorting gate into a local inventory archive.
Successive bundles illustrate gathering pages before saving a complete inventory.

The documented collection request is GET /api/v1/workflows. Send X-N8N-API-KEY on every request. The documented default page size is 100 and maximum is 250; this example requests 100. Omit active, name, tags and project filters. Follow this sequence:

  1. Request the workflow collection without inventory-narrowing filters.
  2. Accumulate each page's data, rejecting duplicate workflow IDs.
  3. Pass nextCursor unchanged as the next cursor parameter.
  4. Finish when nextCursor is null; reject repeated cursors or malformed responses.
  5. Save the complete ID-to-name mapping with sorted keys.

The following is suggested editorial example code, not a tested n8n tool. Save the next two code paragraphs, in order, as inventory.py. It uses Python's standard library. Run it with python3 inventory.py after setting the environment variables. The response-envelope detail comes partly from n8n's moving-branch maintainer reference, not a release-specific client guarantee.

import json, os from pathlib import Path from urllib.parse import urlencode from urllib.request import Request, urlopen root = os.environ['N8N_API_ROOT'].rstrip('/') key = os.environ['N8N_API_KEY'] items, seen, cursor = {}, set(), None while True: params = {'limit': 100} if cursor is not None: params['cursor'] = cursor request = Request(root + '/workflows?' + urlencode(params), headers={'X-N8N-API-KEY': key}, method='GET') with urlopen(request, timeout=30) as response: page = json.load(response) if not isinstance(page, dict) or not isinstance(page.get('data'), list) or 'nextCursor' not in page: raise ValueError('Incomplete collection: malformed page')

for workflow in page['data']: identifier, name = workflow['id'], workflow['name'] if not isinstance(identifier, str) or not isinstance(name, str) or identifier in items: raise ValueError('Incomplete collection: invalid or duplicate ID/name') items[identifier] = name cursor = page['nextCursor'] if cursor is None: break if not isinstance(cursor, str) or not cursor or cursor in seen: raise ValueError('Incomplete collection: invalid or repeated cursor') seen.add(cursor) with open('inventory.candidate.json', 'w', encoding='utf-8') as output: json.dump(items, output, sort_keys=True, ensure_ascii=False, indent=2) print('Complete collection saved as inventory.candidate.json')

The script writes only after collection completes. After a failed run, do not compare an older candidate file. Keep your previous complete baseline separately. Sorted keys make the ID-keyed mapping repeatable regardless of API ordering. Store collection metadata separately.

Sources: Authentication | Connect | n8n Docs, Workflow | Connect | n8n Docs, Pagination | Connect | n8n Docs, n8n-docs/docs/connect/n8n-api/pagination.md at main · n8n-io/n8n-docs · GitHub, n8n/.agents/skills/public-api/reference.md at master · n8n-io/n8n · GitHub, json — JSON encoder and decoder — Python 3.13.16 documentation

3. Compare snapshots and review the result

Two workflow inventory trays show an added token, an absent token and a changed name tab.
Paired trays illustrate the added, missing and renamed categories used in the suggested comparison.

After your first successful collection, retain the candidate as inventory.previous.json. On a later successful run, save this suggested comparison code as compare.py and run python3 compare.py. It loads both JSON mappings and compares IDs before names.

import json with open('inventory.previous.json', encoding='utf-8') as source: before = json.load(source) with open('inventory.candidate.json', encoding='utf-8') as source: after = json.load(source) report = { 'added': {k: after[k] for k in sorted(after.keys() - before.keys())}, 'missing': {k: before[k] for k in sorted(before.keys() - after.keys())}, 'renamed': {k: {'before': before[k], 'after': after[k]} for k in sorted(before.keys() & after.keys()) if before[k] != after[k]} } print(json.dumps(report, sort_keys=True, ensure_ascii=False, indent=2))

These synthetic examples illustrate expected comparisons, not observed test results. A missing entry means no longer observed; review access and collection conditions before interpreting it as a deletion.

Synthetic comparison examples
PreviousCandidateReport
a: Ordersa: OrdersAll categories empty
a: Ordersa: Orders; b: LeadsAdded b
a: Orders; b: Leadsa: OrdersMissing b
a: Ordersa: Order intakeRenamed a

We'd assign a reviewer before replacing the baseline: a difference report is most useful when someone decides what each change means.

Sources: Workflow | Connect | n8n Docs, json — JSON encoder and decoder — Python 3.13.16 documentation

4. Troubleshoot before accepting a snapshot

The n8n API workflow reference documents these response meanings. Use the suggested checks below to investigate, rather than treating each status as a complete diagnosis.

Documented statuses and suggested checks
StatusMeaningSuggested check
400Invalid or malformed requestCheck parameters and unchanged cursor
401UnauthorizedCheck key and authentication header
403ForbiddenReview account access and Enterprise scopes

Sources: Workflow | Connect | n8n Docs, n8n-docs/docs/connect/n8n-api/authentication.md at main · n8n-io/n8n-docs · GitHub, Authentication | Connect | n8n Docs, n8n-docs/docs/connect/n8n-api/pagination.md at main · n8n-io/n8n-docs · GitHub

Put this into practice

Hands-on n8n challenges

Pick a challenge and build a working workflow in your own n8n environment, with five progressive tips per challenge.

Try a hands-on challenge

For your team

Custom n8n training programs for one team or department, run on your own n8n instance with your own tools and data.

Training for your team

n8n skills assessment

A free quiz of about 20 minutes: 30 questions in 10 skill areas and a level from Beginner to Expert. On AI Adoption Score, another project by the author of this site.

Get your n8n level