mcpField
N
n8n:public-api

n8n:public-api

github.com/n8n-io開発209.8k91 回インストール1 日前に更新
リポジトリ

n8n:public-api について

n8n Public API v1 を拡張する開発者向けのスキルです。コントローラー、DTO、認可、ページネーション、OpenAPI、テストの規約を示し、公開契約を保つ変更を支援します。

主な機能

  1. 01コントローラーとサービスの境界
  2. 02厳格な公開 DTO 規約
  3. 03API キーと RBAC による認可
  4. 04カーソルベースの一覧ページネーション
  5. 05OpenAPI の生成と登録
  6. 06統合テストの指針

活用シーン

  1. 01Public API エンドポイントの追加
  2. 02レガシーエンドポイントの移行
  3. 03カーソルページネーション付き一覧の実装
  4. 04認可と入力検証のテスト

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/n8n-io/n8n --skill n8n:public-api

インストール後、Claude Code で/n8n:public-apiを入力して読み込まれたか確認します。

同梱ファイルreference.md

詳細

公開 API v1

公開 API v1 は packages/cli/src/public-api/v1/ にあり、API キー認証と PublicApiControllerRegistry (packages/cli/src/public-api/public-api-controller.registry.ts)による公開エラー形式を使って /api/v1 にマウントされています。

ルールは 2 つの階層に分かれます。不変条件(決して破ってはいけません)とチームのデフォルト(既存の公開契約に反する場合を除き、従ってください)です。このスキルとコードの詳細が食い違う場合は、コードが優先されます。そのため、以下のファイルを開いてください。これはコードを確認する理由であり、チームのデフォルトを省略してよいという意味ではありません。

絶対に守るルール

  • 新しいエンドポイントは、v1/controllers/ 配下の @PublicApiController クラスとし、機能ごとに *.public.controller.ts を 1 つ作成します。
  • 公開 API と内部 REST は、別々の HTTP サーフェスです。公開コントローラーから内部コントローラー/エンドポイントを呼び出すことはありません。どちらも同じサービスを再利用します。
  • コントローラーとハンドラーはサービスに処理を委譲します。リポジトリや Container.get(…Repository) をインポートしてはいけません(no-repository-in-public-api-handler)。
  • 入出力には @n8n/api-types の DTO を使用します。すべての JSON ルートで @ApiResponse(Dto) を宣言します。
  • 各コントローラーは v1/controllers/index.ts の副作用インポートで登録します(そうしないと public-api-controllers.test.ts が失敗します)。
  • レガシーエンドポイントを移行する際は、公開契約を変更してはいけません。

これらは n8n-local-rules ESLint ルールです(packages/cli/eslint.config.mjs を参照)。インラインで無効化することはできません(no-public-api-guardrail-disable)。そこにある off 許可リストは、既存のレガシーファイルのみを対象としています。このリストは縮小のみ可能で、追加してはいけません。

チームのデフォルト

  • コード自体がドキュメントとして機能するように書きます。スキーマ、デコレーター、テストだけでルールが明確になるようにし、コメントに頼らないでください。
  • リストエンドポイント:カーソルベースのページネーションを使用します(内部 API ではカーソルベースとページベースの両方を使用しますが、内部エンドポイントのモデルをそのままコピーしないでください)。
  • ページネーションの引数は常に offset と limit にします。追加するサービスメソッド、ハンドラー呼び出し、リポジトリメソッドのすべてに適用します。TypeORM の名称である skip/take は使用しないでください。skip/take への変換は、リポジトリ内の TypeORM find 呼び出しでのみ行います。公開クエリ文字列は引き続き cursor + limit です。offset はデコードされたカーソルのフィールドで、サービスに渡される値であり、クライアント向けのパラメーターではありません。
  • 更新には PATCH ではなく、オブジェクト全体を指定する PUT を使用します。成功した GET のレスポンスボディは、サーバー管理フィールド/不変フィールドを除き、同じリソースへの PUT のリクエストボディとして使用できるようにします(ラウンドトリップ)。
  • 入力 DTO は厳密にし、出力 DTO は公開フィールドの許可リストにします。
  • 実際のシークレット/トークンをレスポンスやエラー詳細に決して返さないでください。リソースのセンチネル/プレースホルダーでマスクするか、省略します。PUT でそのセンチネルを返した場合は保持し、それ以外の値であれば置き換えます。詳細: 更新と書き込み専用のシークレット。
  • 「接続/設定のテスト」エンドポイントでは、リクエスト本文を検証します(保存前にテスト)。

アーキテクチャ

公開ルートと内部ルートは、HTTP に依存しない 1 つの共有サービスを介する兄弟ルートです。互いを呼び出すことはありません。

GET /rest/tags    → TagsController         ┐  JWT auth, internal shape
                                            ├─→ TagService
GET /api/v1/tags  → TagsPublicController   ┘  API-key auth, public DTO

サービスの動作を再利用します。公開契約と内部契約が意図的に同一である場合に限り DTO を再利用します。それ以外の場合は、UI 向けの内部形式に依存しない、公開 API 専用の DTO を作成します。

編集する前に

以下を開いてください。こちらが正確な情報源であり、このスキルではありません。

  • v1/controllers/ — tags.public.controller.ts(一覧 + カーソル)または workflows.public.controller.ts(@Param + @ProjectScope)の構造と、バレル用の index.ts を参考にしてください。
  • packages/@n8n/decorators/src/controller/ のデコレーター: public-api-controller.ts、api-key-scope.ts、api-response.ts、 api-error-response.ts、api-summary.ts、api-description.ts、api-tags.ts、 route.ts、scoped.ts、args.ts、licensed.ts。
  • OpenAPI ジェネレーター(上記のデコレーターを読み取るため、コントローラーのルートに手書きの YAML は不要です): v1/openapi-gen/generate.ts、 v1/openapi-gen/decorator-routes.ts。
  • ページネーションヘルパー:v1/shared/services/pagination.service.ts (decodeCursor、encodeNextCursor)。
  • DTO:packages/@n8n/api-types/src/dto/。
  • ゲーティングテスト:v1/__tests__/public-api-controllers.test.ts、 v1/__tests__/scope-parity.test.ts、 v1/openapi-gen/__tests__/generated-spec-drift.test.ts。
  • このリソースの内部コントローラーと、隣接する機能テスト。

コントローラーの宣言

コントローラーは、共有サービスをコンストラクターで注入し、その処理を委譲する @PublicApiController('/base') マーク付きのクラスです。v1/controllers/ にある既存のコントローラーから、同じ操作タイプと認証モデルのものを参考にしてください。該当するものだけを再利用します。デコレーターはすべて @n8n/decorators から使用します。

デコレーター用途
@PublicApiController('/base')クラスマーカー。ルートを /api/v1/base にマウントします。
@Get/@Post/@Put/@Patch/@Delete('/path')ルートメソッド。
@ApiKeyScope('res:action')API キーの権限チェック。
@ProjectScope/@GlobalScope('res:action')ユーザー RBAC チェック。
@ApiResponse(status) / @ApiResponse(status, Dto)成功ステータスと(任意の)出力 DTO。レジストリーが戻り値を .parse() して不要なフィールドを除去します。ルートごとに 1 つだけ指定してください。2 つ目の @ApiResponse を指定するとエラーになります。204 には DTO もバイナリー本文も指定できず、指定するとエラーになります。バイナリーのレスポンス本文({ body, headers? } として返す場合)には、@ApiResponse(status, { mediaType, description?, headers? }) を使用してください。バイナリーレスポンス本文を参照してください。
@ApiErrorResponse(status)ドキュメントに記載する追加の非 2xx ステータス(例:404、409)を宣言します。複数ある場合は重ねて指定します。400/401/403 は自動的に追加されます(本文/クエリが存在する場合、常に追加、@ApiKeyScope がある場合にそれぞれ追加)。これらを自分で宣言しないでください。
@ApiSummary(text) / @ApiDescription(text) / @ApiTags([...])OpenAPI の概要/説明/タグ。@ApiTags は指定した順序にかかわらず、アルファベット順に並べ替えます。すべて任意ですが、実際のルートではすべて指定することが期待されています。
@Query / @Body / @Param('name')Z.class DTO/パスパラメーターを使ってバインドし、検証します。@Body はデフォルトで JSON です。代わりに @Body({ mediaType: 'multipart/form-data', uploadLimits }) を指定すると、multipart/form-data の本文を受け取ります。リクエスト本文のメディアタイプを参照してください。
@Licensed('feat')単一の BooleanLicenseFeature に基づいてルートを制限します。PublicApiControllerRegistry は独自のライセンスミドルウェア(認証/@ApiKeyScope/@ProjectScope

認可(間違いやすい点)

  • @ApiKeyScope(API キーに付与されている権限)と @ProjectScope/@GlobalScope (ユーザーが実行できる操作)は独立しています。モデルに両方が必要な場合は、両方を使用してください。
  • すべてのパスパラメーターに {resource}Id という名前を付けてください(例:workflowId、credentialId、 projectId、…)。汎用的な :id / {id} は使用しないでください。これは Public API の 命名規則です。API の自己文書化を促し、型付き SDK のコード生成で id ではなく実際の引数名を使用できます。 @ProjectScope は req.params をそのまま読み取り、id を再マッピングしません。認可対象は キー名との完全一致(workflowId、credentialId、projectId、dataTableId、 …)で解決されるため、@ProjectScope を指定したルートで汎用的な id を使うと、多くの場合そのまま失敗します。 @GlobalScope またはスコープなしのルートでは同じ形で失敗しませんが、それでもこの規則に従ってください。
  • @ApiKeyScope が受け取るのは、文字列、{ anyOf: [...] }、または { allOf: [...] } です。配列だけを 渡すことはできません。スコープは権限レジストリ(@n8n/permissions の API_KEY_RESOURCES)に存在する必要があります。 scope-parity.test.ts は、レジストリに存在しないスコープがあると失敗します。

DTO

  • 公開レスポンスの形状は明示的に構築してください。ORM エンティティを返し、@ApiResponse のフィールド除去で フィールドを隠すことに頼らないでください。
  • 出力 DTO は許可リストとして扱ってください。ネストされたリレーション、所有権フィールド、トークン、 暗号化された値を再確認してください。
  • 出力 DTO が制限するのは返すフィールドであり、それらに設定できる値ではありません。 レジストリはハンドラーの戻り値を DTO に照らして解析するため、スキーマで拒否された値があると 500 になります。既存の行に含まれる可能性のある値を受け入れられるよう、スキーマは十分に緩くしてください。
  • エンティティ型ではなく、ルートが読み込んだリレーションからレスポンスを構築してください。 TypeORM のリレーションは明示的に有効化する必要があるため、同じエンティティを扱う 2 つのルートでも 返す形状は異なることがあります。
  • 入力 DTO は厳密にして、未知のフィールドや一部だけのフィールドが暗黙に受け入れられないようにしてください。 Z.class(shape, { strict: true }) を使用します。
  • シークレット:実際のシークレットは決して返さないでください。リソースのセンチネル値/プレースホルダーを使用するか、 省略してください。更新と書き込み専用シークレットを参照してください。

リストエンドポイント(カーソルページネーション)

tags.public.controller.ts のカーソル処理をコピーしてください。入力 DTO では limit: publicApiPaginationSchema.limit と cursor: z.string().optional() を指定します。 スキーマから limit を取り出し、publicApiPaginationSchema 全体を展開しないでください (このスキーマには offset も含まれていますが、Public API のクエリパラメーターとして使用してはいけません)。 共有ページネーションサービスの decodeCursor / encodeNextCursor を使用してください。カーソルは不透明な値です。 最後のページでは nextCursor: null とし、裸の配列ではなく { data, nextCursor } を返してください。 無効なカーソルは 400 になります。既存のエンドポイントのカーソルの意味はそのまま維持してください。 ただし、offset パラメーターは維持すべき仕様ではなく、取り除くべき不具合です。詳細: リストエンドポイントとカーソルページネーション。

接続チェックリスト

  1. v1/controllers/<feature>.public.controller.ts と、v1/controllers/index.ts での副作用インポート。
  2. @n8n/api-types に公開 DTO を追加し、バレル(src/dto/)からエクスポートします。
  3. 権限レジストリに @ApiKeyScope の値が存在することを確認します。
  4. コントローラールートの OpenAPI パスや x-required-scope を手書きしないでください。ジェネレーター(v1/openapi-gen/generate.ts)が、デコレーター(@ApiSummary/@ApiDescription/@ApiTags/@ApiKeyScope/@ApiResponse/@ApiErrorResponse)から生成します。フルの pnpm build を実行し、再生成された handlers/<feature>/spec/paths/*.generated.yml のフラグメントと openapi.decorator-routes.generated.yml をコミットしてください。古いままの場合、generated-spec-drift.test.ts によって CI が失敗します。コントローラーを変更した後は、pnpm run build:data だけでは不十分です。これはすでにコンパイル済みの dist/ に対してジェネレーターを実行するため、先に tsc を実行しないと、新規または変更したコントローラーが反映されないままになります。
  5. ルートの @ApiTags で新しいタグを使用する場合は、そのタグを v1/openapi.yml の tags: 配列に宣言してください。x-displayName と、親タグのいずれかを指定する x-parent を設定します。子タグはアルファベット順に並べてください。GitBook は表示名からページ URL を生成するため、ドキュメントの URL を確認せずに既存の x-displayName を変更しないでください。タグが宣言されていない場合、または順序が正しくない場合、openapi-tags.test.ts によって失敗します。
  6. packages/nodes-base/nodes/N8n/n8n-api-coverage.json にルートを追加します。
  7. テスト。

テスト

常に、正常系、入力検証エラー、API キーのスコープ不足、RBAC による拒否を網羅してください。ビジネス処理のカバレッジには、packages/cli/test/integration/public-api/ の利用を優先してください(実際の HTTP と DB を使用します)。モックサービスを使った単体テストでは代替できません。該当するケース(カーソルページ、未検出/競合、機密フィールドが含まれないこと、認証情報の保持/置換、マイグレーション契約)を追加してください。テストマトリックスを参照し、最も近い既存のテストに合わせてください。

詳細(reference.md)

コメント