{"id":19857723,"url":"https://github.com/devlikeapro/n8n-openapi-node","last_synced_at":"2025-04-06T01:05:55.722Z","repository":{"id":257756836,"uuid":"859227115","full_name":"devlikeapro/n8n-openapi-node","owner":"devlikeapro","description":"Turn Your OpenAPI (Swagger) spec into a n8n node!","archived":false,"fork":false,"pushed_at":"2025-03-18T02:52:18.000Z","size":1282,"stargazers_count":50,"open_issues_count":5,"forks_count":11,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-30T00:05:06.027Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/devlikeapro.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-18T09:57:18.000Z","updated_at":"2025-03-22T13:56:12.000Z","dependencies_parsed_at":"2024-09-18T13:37:45.599Z","dependency_job_id":"8cdecd9c-16cb-4fc8-96b1-9d3e669cb903","html_url":"https://github.com/devlikeapro/n8n-openapi-node","commit_stats":null,"previous_names":["devlikeapro/n8n-openapi-node"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devlikeapro%2Fn8n-openapi-node","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devlikeapro%2Fn8n-openapi-node/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devlikeapro%2Fn8n-openapi-node/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devlikeapro%2Fn8n-openapi-node/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/devlikeapro","download_url":"https://codeload.github.com/devlikeapro/n8n-openapi-node/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247419859,"owners_count":20936012,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-12T14:19:33.731Z","updated_at":"2025-04-06T01:05:55.690Z","avatar_url":"https://github.com/devlikeapro.png","language":"TypeScript","funding_links":["https://patreon.com/devlikeapro"],"categories":["TypeScript"],"sub_categories":[],"readme":"# @devlikeapro/n8n-openapi-node\n\n\n![openapi logo](openapi.png)\n![n8n logo](n8n.png)\n\nTurn Your **OpenAPI** (**Swagger**) spec into a **n8n node**!\n\n[![npm version](https://img.shields.io/npm/v/@devlikeapro/n8n-openapi-node.svg)](https://www.npmjs.com/package/@devlikeapro/n8n-openapi-node)\n\n---\n\n\u003c!-- toc --\u003e\n\n- [Quick Start](#quick-start)\n  * [Installation](#installation)\n  * [Usage](#usage)\n- [How it works](#how-it-works)\n  * [Resource](#resource)\n  * [Operation](#operation)\n  * [Query Parameters](#query-parameters)\n  * [Request Body](#request-body)\n  * [Headers](#headers)\n- [Customization](#customization)\n  * [Resource](#resource-1)\n  * [Operation](#operation-1)\n  * [Fields](#fields)\n- [Use Cases](#use-cases)\n- [FAQ](#faq)\n  * [I have only OpenAPI v2 spec, what can I do?](#i-have-only-openapi-v2-spec-what-can-i-do)\n  * [I have openapi.yaml spec, what can I do?](#i-have-openapiyaml-spec-what-can-i-do)\n  * [How to set up credentials from OpenAPI v3 spec?](#how-to-set-up-credentials-from-openapi-v3-spec)\n  * [Why it doesn't work with my OpenAPI spec?](#why-it-doesnt-work-with-my-openapi-spec)\n- [Support the project](#support-the-project)\n\n\u003c!-- tocstop --\u003e\n\n# Quick Start\n\nIf you have OpenAPI specification - you can easily in few minutes create\n[your community node](https://docs.n8n.io/integrations/community-nodes/usage/) for n8n!\n\nIt'll still require to create and publish `n8n-nodes-\u003cyourproject\u003e` npm package,\nbut you can use this package to generate most of the code.\n\n\n👉 We recommend using one of repo for the `n8n-nodes-\u003cyourproject\u003e` package:\n\n- https://github.com/devlikeapro/n8n-nodes-petstore - Petstore example generated from OpenAPI v3 spec\n- https://github.com/n8n-io/n8n-nodes-starter - Official n8n nodes starter template\n\nFind more real-world examples in [Use Cases](#use-cases) section.\n\n![example](node.png)\n\n## Installation\n\nAdd `@devlikeapro/n8n-openapi-node` as dependency\n\n```bash\nnpm install @devlikeapro/n8n-openapi-node\n# OR\npnpm add @devlikeapro/n8n-openapi-node\n# OR\nyarn add @devlikeapro/n8n-openapi-node\n```\n\n\n## Usage\n\n1. Add your `openapi.json` to `src/{NodeName}` folder\n   (use **OpenAPI v3** and **json**, see [FAQ](#faq) if you don't have it)\n\n2. Get your `Node.properties` from OpenAPI v3 spec:\n\n```typescript\nimport {INodeType, INodeTypeDescription, NodeConnectionType} from 'n8n-workflow';\nimport {N8NPropertiesBuilder, N8NPropertiesBuilderConfig} from '@devlikeapro/n8n-openapi-node';\nimport * as doc from './openapi.json'; // \u003c=== Your OpenAPI v3 spec\n\nconst config: N8NPropertiesBuilderConfig = {}\nconst parser = new N8NPropertiesBuilder(doc, config);\nconst properties = parser.build()\n\nexport class Petstore implements INodeType {\n  description: INodeTypeDescription = {\n    displayName: 'Petstore',\n    name: 'petstore',\n    icon: 'file:petstore.svg',\n    group: ['transform'],\n    version: 1,\n    subtitle: '={{$parameter[\"operation\"] + \": \" + $parameter[\"resource\"]}}',\n    description: 'Interact with Petstore API',\n    defaults: {\n      name: 'Petstore',\n    },\n    inputs: [NodeConnectionType.Main],\n    outputs: [NodeConnectionType.Main],\n    credentials: [\n      {\n        name: 'petstoreApi',\n        required: false,\n      },\n    ],\n    requestDefaults: {\n      headers: {\n        Accept: 'application/json',\n        'Content-Type': 'application/json',\n      },\n      baseURL: '={{$credentials.url}}',\n    },\n    properties: properties, // \u003c==== HERE\n  };\n}\n```\n\n# How it works\n\n`N8NPropertiesBuilder` extracts few entities from OpenAPI v3 to your n8n community node:\n\n1. **Resource** - a list of **Tags** from OpenAPI spec\n2. **Operation** - a list of **Operations** from OpenAPI spec (aka **Actions** in n8n)\n3. **Query Parameters** - a list of `operation.parameters` from OpenAPI spec\n4. **Request Body** - a list of `operation.requestBody.content` from OpenAPI spec (only for `application/json`)\n5. **Headers** - a list of `operation.parameters` from OpenAPI spec\n\n## Resource\n\nBy default, it get **Tags** from OpenAPI spec and converts them to **Resource** in n8n.\n\n## Operation\n\nBy default, it gets **Operations** from OpenAPI spec and converts them to **Actions** in n8n.\n\n## Query Parameters\n\nIt gets `operation.parameters` from OpenAPI spec and converts them to **Query Parameters** in n8n.\n\n## Request Body\n\nIt doesn't create the full structure of the request body, only the first level of properties.\nSo if you have request body as\n\n```json\n{\n  \"name\": \"string\",\n  \"config\": {\n    \"id\": 0,\n    \"name\": \"string\"\n  }\n}\n```\n\nit creates 2 fields in n8n:\n\n- `name` - with default value `string`\n- `config` - with default value `{\"id\": 0, \"name\": \"string\"}`\n\n## Headers\n\nIt gets `operation.parameters` from OpenAPI spec and converts them to **Headers** in n8n.\n\n# Customization\n\n## Resource\n\nYou can override the way how to extract **Resource** from **OpenAPI Tag** defining your custom `IResourceParser`:\n\n```typescript\nimport {IResourceParser} from '@devlikeapro/n8n-openapi-node';\n\nexport class CustomResourceParser {\n  CUSTOM_DESCRIPTION = {\n    \"cats\": \"Cats are cute\",\n  }\n\n  name(tag: OpenAPIV3.TagObject): string {\n    // Your custom logic here\n    if (tag['X-Visible-Name']) {\n      return tag['X-Visible-Name'];\n    }\n    return lodash.startCase(tag.name);\n  }\n\n  value(tag: Pick\u003cOpenAPIV3.TagObject, \"name\"\u003e): string {\n    // Remove all non-alphanumeric characters\n    const name = tag.name.replace(/[^a-zA-Z0-9_-]/g, '')\n    return lodash.startCase(name)\n  }\n\n  description(tag: OpenAPIV3.TagObject): string {\n    // Your custom logic here\n    return this.CUSTOM_DESCRIPTION[tag.name] || tag.description || '';\n  }\n}\n```\n\nAlternatively, you can use `DefaultResourceParser` and override only the methods you need.\nThe default implementation you can find in [src/ResourceParser.ts](src/ResourceParser.ts)\n\n```typescript\nimport {OpenAPIV3} from 'openapi-types';\nimport * as lodash from 'lodash';\nimport {DefaultResourceParser} from '@devlikeapro/n8n-openapi-node';\n\nexport class CustomResourceParser extends DefaultResourceParser {\n  value(tag: OpenAPIV3.TagObject): string {\n    return lodash.startCase(tag.name.replace(/[^a-zA-Z0-9_-]/g, ''));\n  }\n}\n```\n\nThen you use it in `N8NPropertiesBuilder` in `config.resource`:\n\n```typescript\nimport {N8NPropertiesBuilder, N8NPropertiesBuilderConfig} from '@devlikeapro/n8n-openapi-node';\nimport * as doc from './openapi.json';\n\nimport {CustomResourceParser} from './CustomResourceParser';\n\nconst config: N8NPropertiesBuilderConfig = {\n  resource: new CustomResourceParser()\n}\nconst parser = new N8NPropertiesBuilder(doc, config);\nconst properties = parser.build()\n```\n\nFind real example in [@devlikeapro/n8n-nodes-waha](https://github.com/devlikeapro/n8n-nodes-waha) repository.\n\n## Operation\n\nYou can override the way how to extract **Operation** from **OpenAPI Operation** defining your custom\n`IOperationParser`:\n\n```typescript\nimport {IOperationParser} from '@devlikeapro/n8n-openapi-node';\n\nexport class CustomOperationParser implements IOperationParser {\n  shouldSkip(operation: OpenAPIV3.OperationObject, context: OperationContext): boolean {\n    // By default it skips operation.deprecated\n    // But we can include all operations\n    return false\n  }\n\n  name(operation: OpenAPIV3.OperationObject, context: OperationContext): string {\n    if (operation['X-Visible-Name']) {\n      return operation['X-Visible-Name'];\n    }\n    return lodash.startCase(operation.operationId)\n  }\n\n  value(operation: OpenAPIV3.OperationObject, context: OperationContext): string {\n    return lodash.startCase(operation.operationId)\n  }\n\n  action(operation: OpenAPIV3.OperationObject, context: OperationContext): string {\n    // How operation is displayed in n8n when you select your node (right form)\n    return operation.summary || this.name(operation, context)\n  }\n\n  description(operation: OpenAPIV3.OperationObject, context: OperationContext): string {\n    return operation.description || operation.summary || '';\n  }\n}\n```\n\nAlternatively, you can use `DefaultOperationParser` and override only the methods you need.\nThe default implementation you can find in [src/OperationParser.ts](src/OperationParser.ts)\n\n```typescript\nimport {DefaultOperationParser} from '@devlikeapro/n8n-openapi-node';\n\nexport class CustomOperationParser extends DefaultOperationParser {\n  name(operation: OpenAPIV3.OperationObject, context: OperationContext): string {\n    // NestJS add operationId in format CatController_findOne\n    let operationId: string = operation.operationId!!.split('_').slice(1).join('_');\n    if (!operationId) {\n      operationId = operation.operationId as string;\n    }\n    return lodash.startCase(operationId);\n  }\n}\n```\n\nThen you use it in `N8NPropertiesBuilder` in `config.operation`:\n\n```typescript\nimport {N8NPropertiesBuilder, N8NPropertiesBuilderConfig} from '@devlikeapro/n8n-openapi-node';\nimport * as doc from './openapi.json';\nimport {CustomOperationParser} from './CustomOperationParser';\n\nconst config: N8NPropertiesBuilderConfig = {\n  operation: new CustomOperationParser()\n}\nconst parser = new N8NPropertiesBuilder(doc, config);\nconst properties = parser.build()\n```\n\nFind real example in [@devlikeapro/n8n-nodes-waha](https://github.com/devlikeapro/n8n-nodes-waha) repository.\n\n## Fields\n\nYou can override some values for fields at the end, when full `properties` are ready.\n\nHere's example how you can override `session` field value (which has `'default'` string default value) to more n8n\nsuitable `=${$json.session}}`:\n\n```typescript\nimport {Override} from '@devlikeapro/n8n-openapi-node';\n\nexport const customDefaults: Override[] = [\n  {\n    // Find field by fields matching\n    find: {\n      name: 'session',\n      required: true,\n      type: 'string',\n    },\n    // Replace 'default' field value\n    replace: {\n      default: '={{ $json.session }}',\n    },\n  },\n];\n```\n\nThen you use it in `N8NPropertiesBuilder`:\n\n```typescript\n\nimport {N8NPropertiesBuilder, N8NPropertiesBuilderConfig} from '@devlikeapro/n8n-openapi-node';\nimport * as doc from './openapi.json';\nimport {customDefaults} from './customDefaults';\n\nconst parser = new N8NPropertiesBuilder(doc);\nconst properties = parser.build(customDefaults);\n```\n\nFind real example in [@devlikeapro/n8n-nodes-waha](https://github.com/devlikeapro/n8n-nodes-waha) repository.\n\n# Use Cases\n\nHere's n8n community nodes generated from OpenAPI specifications you can use for reference:\n\n- [@devlikeapro/n8n-nodes-petstore](https://github.com/devlikeapro/n8n-nodes-petstore) - Petstore example generated from\n  [Petstore openapi.json](https://github.com/OAI/OpenAPI-Specification/blob/main/examples/v3.0/petstore.yaml)\n- [@devlikeapro/n8n-nodes-chatwoot](https://github.com/devlikeapro/n8n-nodes-chatwoot) - ChatWoot n8n community node\n  from\n  [https://www.chatwoot.com/developers/api/](https://www.chatwoot.com/developers/api/). Defines credentials as well (\n  manually)\n- [@devlikeapro/n8n-nodes-waha](https://github.com/devlikeapro/n8n-nodes-waha) - **WAHA** - Self-hosted **WhatsApp HTTP\n  API** you can run in a click!\n\n# FAQ\n\n## I have only OpenAPI v2 spec, what can I do?\n\nPaste your OpenAPI 2.0 definition into https://editor.swagger.io and select **Edit \u003e Convert to OpenAPI 3** from the\nmenu.\n\nhttps://stackoverflow.com/a/59749691\n\n## I have openapi.yaml spec, what can I do?\n\nPaste your yaml spec to https://editor.swagger.io and select **File \u003e Save as JSON** from the menu.\n\n## How to set up credentials from OpenAPI v3 spec?\n\nRight now you need to define it manually.\nCheck [ChatWoot node](https://github.com/devlikeapro/n8n-nodes-chatwoot)\nfor an example.\n\n## Why it doesn't work with my OpenAPI spec?\n\nOpen [a new issue](https://github.com/devlikeapro/n8n-openapi-node/issues) and please attach\nyour openapi.json file and describe the problem (logs are helpful too).\n\n# Support the project\n\nYou can support the project by donating a small amount to help us improve the project even more.\n\n- [https://patreon.com/devlikeapro](https://patreon.com/devlikeapro)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevlikeapro%2Fn8n-openapi-node","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevlikeapro%2Fn8n-openapi-node","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevlikeapro%2Fn8n-openapi-node/lists"}