Stop writing n8n node properties by hand.
Every time you build a custom n8n node for an API, you spend hours: sometimes days: manually defining operations, parameters, and schemas. You copy-paste from Swagger docs, fix edge cases, handle nested $refs, and pray nothing breaks in production.
What if your n8n node properties wrote themselves?
Point this library at any OpenAPI spec: a URL, a local file, YAML or JSON: and get production-ready n8n node properties in seconds. Not a rough draft. Not a skeleton. The real thing.
You found an API you want to integrate with n8n. It has an OpenAPI spec: hundreds of endpoints, nested schemas, authentication flows. You look at the n8n node property format and realize:
- There are hundreds of operations to define
- Schema references (
$ref) go 5, 6, 7 levels deep - allOf composition merges objects in ways that break naive generators
- Some specs use OpenAPI 3.1 with union types like
type: ['string', 'null'] - Circular references crash most parsers
- Half the operations don't even have an
operationId
So you do it by hand. Again. For the 47th API.
This library ends that cycle.
π Any Source, Any Format URL or file. JSON or YAML. OpenAPI 3.0 or 3.1. It just works.
π₯οΈ CLI for Instant Generation One command. No code needed.
npx n8n-openapi-gen --input https://api.example.com/openapi.json --output properties.jsonπ§ Real Schema Support
allOfcomposition: properly merged, not concatenated- Union types (
type: ['string', 'null']): handled natively - Circular
$refs: protected with depth limiting (max 50) - Path-level
$ref: resolved correctly
π·οΈ Smart Naming
Operations without operationId? Generates clean, human-readable names automatically. No undefined_operation_37.
ποΈ Fully Customizable Override parsers, collectors, and behavior. Make it yours.
π¦ Zero Config
npm install β import β build(). That's it.
npm install @n8n-dev/n8n-openapi-node-ultimateimport { N8NPropertiesBuilder, loadOpenApi } from '@n8n-dev/n8n-openapi-node-ultimate';
const doc = await loadOpenApi('https://petstore3.swagger.io/api/v3/openapi.json');
const builder = new N8NPropertiesBuilder(doc);
const properties = builder.build();
// Done. Use `properties` in your n8n node.# From URL
npx n8n-openapi-gen --input https://petstore3.swagger.io/api/v3/openapi.json --output properties.json
# From local file
npx n8n-openapi-gen --input ./openapi.yaml --output properties.json
# Pipe to stdout
npx n8n-openapi-gen --input ./openapi.json| Option | Description |
|---|---|
-i, --input <source> |
OpenAPI spec (URL or file): required |
-o, --output <file> |
Output file (defaults to stdout) |
--pretty |
Pretty-print JSON (default: true) |
-V, --version |
Show version |
-h, --help |
Show help |
import { N8NPropertiesBuilder, loadOpenApi } from '@n8n-dev/n8n-openapi-node-ultimate';
async function generateNodeProperties(specUrl: string) {
const doc = await loadOpenApi(specUrl);
const builder = new N8NPropertiesBuilder(doc);
return builder.build();
}
// Use in your n8n node definition
const properties = await generateNodeProperties('https://api.example.com/openapi.json');#!/bin/bash
npx n8n-openapi-gen \
--input https://api.example.com/openapi.json \
--output ./n8n-node/properties.json
echo "β Properties generated"import { loadOpenApiFromFile, N8NPropertiesBuilder } from '@n8n-dev/n8n-openapi-node-ultimate';
const doc = loadOpenApiFromFile('./my-api.yaml');
const builder = new N8NPropertiesBuilder(doc);
const properties = builder.build();import { DefaultOperationParser, OperationContext } from '@n8n-dev/n8n-openapi-node-ultimate';
import { OpenAPIV3 } from 'openapi-types';
class MyOperationParser extends DefaultOperationParser {
name(operation: OpenAPIV3.OperationObject, context: OperationContext): string {
const id = operation.operationId?.split('_').pop() || 'unknown';
return lodash.startCase(id);
}
}
const builder = new N8NPropertiesBuilder(doc, {
operation: new MyOperationParser(),
});import { DefaultResourceParser } from '@n8n-dev/n8n-openapi-node-ultimate';
class MyResourceParser extends DefaultResourceParser {
value(tag: { name: string }): string {
return tag.name.toLowerCase().replace(/\s+/g, '-');
}
}
const builder = new N8NPropertiesBuilder(doc, {
resource: new MyResourceParser(),
});const overrides: Override[] = [
{
find: { name: 'apiKey' },
replace: { default: '={{ $credentials.apiKey }}' },
},
];
const properties = builder.build(overrides);The main class. Takes a parsed OpenAPI document, returns n8n properties.
const builder = new N8NPropertiesBuilder(doc, config?);
const properties = builder.build(overrides?);Auto-detects URL vs file path. Loads and parses the spec.
const doc = await loadOpenApi('https://api.example.com/openapi.json');
const doc = await loadOpenApi('./openapi.yaml');Fetch from URL. Supports JSON and YAML.
Load from local file. Supports JSON and YAML.
"Does it support OpenAPI 3.1?" Yes. Union types, nullable types, all of it.
"Can I load specs from a URL?"
Yes. loadOpenApi(url) or CLI --input <url>.
"What about Swagger 2.0?" Convert to OpenAPI 3.x first with swagger2openapi.
"What about circular $refs?"
Built-in protection. Max depth of 50. Won't crash.
"Can I customize the output?"
Yes. Custom parsers for operations and resources, plus Override patterns.
- Fork β
git checkout -b feat/my-feature - Commit β
git commit -m 'feat: add my feature' - Push β
git push origin feat/my-feature - Open a Pull Request
git clone https://github.com/kelvinzer0/n8n-openapi-node-ultimate.git
cd n8n-openapi-node-ultimate
npm install
npm run build
npm testMIT Β© kelvinzer0
Based on n8n-openapi-node by Devlikeapro.