n8nと外のサービスのやり取りは3通りしかありません。相手から送ってもらう(Webhook)、こちらから呼びに行く(HTTP Requestか専用ノード)、外からn8nを操作する(n8nのPublic API)です。この記事では、問い合わせフォームの内容をGoogleスプレッドシート「問い合わせ一覧」に残してSlackの #問い合わせ に知らせる「問い合わせ受付」ワークフローを例に、3通りを全部通します。前提は、n8n 2.44.7(2026年10月時点の安定版)がn8n.example.co.jpのような独自ドメインとHTTPSで動いていることです。
この記事の内容
先に決めること
専用ノードか、HTTP Requestか、Codeか
SlackやGmailのようにサービス名がついた専用ノードがあればそれを使い、無ければHTTP Requestで相手のAPIを直接呼び、それでも書けない処理だけCodeノードに回します。
| 状況 | 使うもの | 理由 |
|---|---|---|
| 専用ノードがあり、やりたい操作が一覧にある | 専用ノード | 認証の画面が用意されていて、項目を選ぶだけで済む |
| 専用ノードはあるが、操作が無い | HTTP Request(Predefined Credential Type) | 専用ノードと同じ認証をそのまま使える |
| 専用ノードが無い(LINE Messaging API・kintoneなど) | HTTP Request(Generic Credential Type) | APIドキュメントどおりに組める |
| 署名の比較など、ノードの組み合わせで書けない | Code | 最後の手段 |
送ってもらうか、取りに行くか
相手が「何か起きたらこのURLに知らせる」仕組みを持っているなら、送ってもらうほうが速く、n8nの負荷も小さくなります。持っていないときだけSchedule Triggerで取りに行きます。
鍵はCredentialsに置く
APIキーやトークンはノードの欄に書かず、Credentials(認証情報)に登録して選びます。直書きが残ると、鍵を変えるときに全部のノードを探して回ることになります。
この記事で作るもの
| ノード | 役割 | 主な設定 |
|---|---|---|
| Webhook | フォームから受ける | POST、Path: inquiry、Header Auth |
| Edit Fields (Set) | 受けたデータを整える | 会社名・氏名・メール・本文・受付日時 |
| Google Sheets | 「問い合わせ一覧」に1行足す | Append Row |
| Slack | #問い合わせ に知らせる | Message の Send |
| Respond to Webhook | フォームに返事を返す | Respond With: JSON |
| HTTP Request(応用) | LINE・kintoneに送る | Generic Credential Type |
| Salesforce(応用) | リードとして登録する | Lead の Create |

Webhookで受ける
Test URLとProduction URL
Webhookノードには2つのURLが出ます。違いを知らないと、ほぼ確実に一度は詰まります。
| Test URL | Production URL | |
|---|---|---|
| 形(初期値) | https://n8n.example.co.jp/webhook-test/inquiry | https://n8n.example.co.jp/webhook/inquiry |
| 受け付ける間 | 「Listen for test event」(テストイベントを待つ)を押してから120秒 | ワークフローを公開(Publish)している間ずっと |
| 受けたデータ | エディタの画面に出る | 画面には出ない。「Executions」(実行履歴)で見る |
n8n 2.x では、1.x で「有効化(Activate)」と呼んでいた操作が「公開(Publish)」になっています。
手順
- 新しいワークフローを作り、名前を「問い合わせ受付」にする。
- 最初のノードに「Webhook」を追加する。
- 「HTTP Method」を
POSTにする。 - 「Path」を
inquiryにする(初期値はランダムな文字列)。 - 「Respond」を「Using ‘Respond to Webhook’ Node」にする。
- 「Listen for test event」を押す。
- 120秒以内に、手元のターミナルから下のcurlを送る。
- 右側のOUTPUTに、送った内容が出たことを確かめる。
curl -X POST 'https://n8n.example.co.jp/webhook-test/inquiry' \
-H 'Content-Type: application/json' \
-d '{"company":"株式会社サンプル","name":"山田 太郎","email":"taro@example.com","message":"料金表を送ってください"}'


受けたデータは body(中身)、headers、params(URLの中の変数)、query(URLの ? 以降)に分かれて入ります。会社名は $json.company ではなく $json.body.company です。ここを間違えて後ろのノードが全部空になる例をよく見ます。手元のPCで動かしているn8nには外のフォームから届かないので、試すだけならcurlで自分に送れば足ります。

Header Authで鍵をかける
Production URLは、URLを知っていれば誰でも送れます。Webhookノードの「Authentication」には「Basic Auth」「Header Auth」「JWT Auth」「None」があり、フォームから送るならHeader Authが扱いやすいです。
- 「Authentication」を「Header Auth」にする。
- 新しいCredentialを作り、「Name」に
X-Form-Token、「Value」に長いランダムな文字列を入れる。 - curlに
-H 'X-Form-Token: (同じ文字列)'を足して送り、通ることを確かめる。 - ヘッダーを外して送り、拒否されることも確かめる。

この鍵をブラウザで動くJavaScriptに書いてはいけません。ページのソースを見れば読めるからです。フォームはいったん自社サイトのサーバーで受け、サーバー側からn8nへ送ります。PHPなら次の形で、鍵はサーバーの環境変数に置きます。
<?php
$payload = json_encode([
'company' => $_POST['company'] ?? '',
'name' => $_POST['name'] ?? '',
'email' => $_POST['email'] ?? '',
'message' => $_POST['message'] ?? '',
], JSON_UNESCAPED_UNICODE);
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'header' => "Content-Type: application/json; charset=utf-8\r\n"
. "X-Form-Token: " . getenv('N8N_FORM_TOKEN') . "\r\n",
'content' => $payload,
'timeout' => 10,
'ignore_errors' => true,
]]);
$result = file_get_contents('https://n8n.example.co.jp/webhook/inquiry', false, $ctx);
運用しているn8nで、サーバーに残したバックアップファイル(.bak)からWebhookのURLが誰でも読める状態になっていたことがあります。送信元のサーバーが決まっているなら、「Options」の「IP(s) Allowlist」も足します。n8nがリバースプロキシの後ろにいるときは、環境変数 N8N_PROXY_HOPS にプロキシの段数を入れないと、許可したIPからでも弾かれます。
Respond to Webhookで返事を返す
- ワークフローの最後に「Respond to Webhook」を追加する。
- 「Respond With」を「JSON」にし、
{"ok": true}と入れる。 - 「Add Option」から「Response Code」を足し、
200にする。

Respond to Webhookを通らずに終わると標準のメッセージが200で、その前でエラーになると500で返ります。2個目のRespond to Webhookは無視されます。送信後に完了ページへ移したいときは「Respond With」の「Redirect」を使います。
受けたデータを整える
Webhookの直後に「Edit Fields (Set)」を1つ置き、ここで形を決めます。
- Webhookの後ろに「Edit Fields (Set)」を追加し、「Mode」を「Manual Mapping」にする。
- 左の入力から body の各項目を「Fields to Set」へドラッグする。
- 項目名をスプレッドシートの列名に合わせて「会社名」「氏名」「メール」「本文」に直す。
- 「受付日時」を新しく足し、値を式にする。
| 項目 | 式 | ねらい |
|---|---|---|
| 会社名 | {{ $json.body.company.trim() }} | 前後の空白を落とす |
| 氏名 | {{ $json.body.name.replace(/[\t\r\n]+/g, ' ').trim() }} | タブ・改行を半角スペースにする |
| 受付日時 | {{ $now.setZone('Asia/Tokyo').format('yyyy-LL-dd HH:mm') }} | 日本時間で読める形にする |

氏名のタブと改行を消すのには理由があります。運用しているn8nで、氏名にタブが混ざった1件だけ後ろの突合ノードが落ち、直して流し直したら通知が二重に飛びました。人が手で入れる欄は最初に掃除します。
日付はLuxonという日付ライブラリで扱います。文字列の日付は DateTime.fromISO('2026-10-26T09:00:00') で日付に読み直してから計算します。n8nの時刻の基準は何も設定しないとニューヨーク時間なので、サーバー全体は環境変数 GENERIC_TIMEZONE=Asia/Tokyo、ワークフローごとは設定画面のタイムゾーンで日本時間にします。
配列が1件ずつに分かれる仕組み
n8nはノード間で「アイテム」の並びを渡し、アイテムが3つあれば後ろのノードは3回動きます。APIから {"records": [ ... ]} のように配列が1つのアイテムで返ったときは、「Split Out」ノードの「Field to Split Out」に records を入れると1件ずつに分かれます。逆に意図せず分かれてSlackに何十回も通知が飛ぶときは、そのノードの「Settings」で「Execute Once」(最初のアイテムで1回だけ実行)をオンにします。
HTTP Requestで呼ぶ
APIドキュメントの読み方
どのサービスのAPIドキュメントでも、見る場所は同じです。
| 見る場所 | HTTP Requestの欄 | 例(LINEのプッシュメッセージ) |
|---|---|---|
| メソッドとURL | 「Method」「URL」 | POST https://api.line.me/v2/bot/message/push |
| 認証 | 「Authentication」 | Authorization: Bearer {チャネルアクセストークン} |
| ボディ | 「Send Body」 | JSONで to と messages |
| 次ページの取り方 | Optionsの「Pagination」 | 送信APIなので無し |
| レート制限とエラー | 「Retry On Fail」と「Batching」 | 2,000リクエスト/秒、429で上限超過 |
cURLを取り込む
- HTTP Requestノードを追加する。
- 「Parameters」タブの「Import cURL」を押す。
- 「Import cURL command」の欄にAPIドキュメントのcurlを貼り、「Import」を押す。
- 取り込まれたトークンをノードから消し、Credentialに移す。
取り込むとノードの設定は上書きされ、値はすべて文字列になります。数値や true/false を保ちたいときは、ボディを「Using JSON」に切り替えて書き直します。

認証のしかた
「Authentication」で「Generic Credential Type」を選ぶと、次の型が使えます。
| 型 | 使う場面 | 入れるもの |
|---|---|---|
| Header Auth | APIキーを独自のヘッダーで送る(kintoneなど) | Name と Value |
| Bearer Auth | Authorization: Bearer トークン(LINEなど) | Bearer Token |
| Query Auth | APIキーをURLの ?key= で送る | Name と Value |
| OAuth2 API | ログイン画面を通して許可をもらう | Grant Type・各URL・Client ID・Client Secret・Scope |
OAuth2の「Grant Type」は「Authorization Code」「Client Credentials」「PKCE」から選び、相手のサービスに登録するリダイレクト先には、Credentialの画面に出る「OAuth Redirect URL」(セルフホストなら https://n8n.example.co.jp/rest/oauth2-credential/callback)を使います。

ページネーション
一覧を取るAPIは、100件ずつのように区切って返します。「Add Option」から「Pagination」を足すと、n8nが続きを取りに行きます。
| Pagination Mode | 使う場面 | 設定例 |
|---|---|---|
| Update a Parameter in Each Request | ページ番号をパラメータで渡すAPI | Type: Query、Name: page、Value: {{ $pageCount + 1 }} |
| Response Contains Next URL | 返事に次ページのURLが入るAPI | Next URL: {{ $response.body["next-page"] }} |
$pageCount は取得済みのページ数で0から始まるので、1ページ目から数えるAPIには +1 します。$response には前回の返事の body・headers・statusCode が入ります。
ページ送りは効いていなくてもエラーになりません。運用しているn8nでkintoneから一覧を取ったとき、offset を独立したパラメータで渡していたため黙って無視され、同じ500件が何度も返っていました。kintoneは query という文字列の中に limit 500 offset 500 のように書く仕様で、limitを書かないと100件で止まり、offsetは10,000件までです。2ページ目の中身が1ページ目と違うことを必ず確かめます。
エラー時のリトライ
| 設定 | 場所 | 効き方 |
|---|---|---|
| Retry On Fail | ノードの「Settings」 | 失敗したら「Max Tries」回まで、「Wait Between Tries (ms)」ずつ待って繰り返す |
| Batching | HTTP Requestの「Options」 | 「Items per Batch」件ずつ「Batch Interval (ms)」空けて送る。1000 なら1秒に1回 |
| On Error | ノードの「Settings」 | 「Stop Workflow」「Continue」「Continue (using error output)」 |
429が出るならBatchingで間隔を空け、それでも出るときにRetry On Failを足します。On Errorを「Continue」にするのは慎重に決めます。運用しているn8nで、kintoneから顧客を探すノードをContinueにしていたら、検索が失敗したときも「該当なし」と同じ空の結果が流れ、実在する顧客からの返信を黙って取りこぼしていました。失敗を扱うなら「Continue (using error output)」にして、エラーの出口にSlack通知をつなぎます。

例:LINEに知らせる
n8nの「Line」ノードはLINE Notify用で、n8n 1.64.0から非推奨です。LINE Notify自体が2025年3月31日でサービスを終えていて、もう動きません。LINEに送るなら、Messaging APIをHTTP Requestで呼びます。
- 「Bearer Auth」のCredentialを作り、チャネルアクセストークンを入れる。
- 「Method」を
POST、「URL」をhttps://api.line.me/v2/bot/message/pushにする。 - 「Send Body」をオンにし、「JSON」の「Using JSON」で下を入れる。
{
"to": "{{ $vars.LINE_TO }}",
"messages": [
{
"type": "text",
"text": {{ JSON.stringify('新しい問い合わせ\n' + $json['会社名'] + ' ' + $json['氏名']) }}
}
]
}
to は友だち追加した人の userId で、Messaging APIのWebhookで届くイベントから取ります。messages は1回5件まで。文字を JSON.stringify で包むのは、" や改行でJSONが壊れるのを防ぐためです。ブロックされている相手に送っても200が返り、実際には届きません。月に送れる通数の上限を超えたときも429が返ります。リトライで二重に届くのを防ぐなら、X-Line-Retry-Key ヘッダーにメッセージごとに固定したUUIDを入れます。24時間以内の同じキーの再送は409で弾かれますが、24時間を過ぎると新しい送信として届きます。
例:kintoneにレコードを追加する
kintoneには専用ノードが無いので、HTTP Requestで「1件のレコードを登録する」APIを呼びます。
- kintoneのアプリでAPIトークンを作り、レコード追加の権限を付ける。
- 「Header Auth」のCredentialで、Nameに
X-Cybozu-API-Token、Valueにトークンを入れる。 - 「Method」を
POST、「URL」をhttps://example.cybozu.com/k/v1/record.jsonにする。 - 「Send Body」の「Using JSON」に下を入れる。
{
"app": 12,
"record": {
"会社名": { "value": "{{ $json['会社名'] }}" },
"氏名": { "value": "{{ $json['氏名'] }}" },
"問い合わせ内容": { "value": {{ JSON.stringify($json['本文']) }} }
}
}
record の中のキーはフィールドコードで、例はフィールドコードを日本語で付けたアプリの場合です。存在しないフィールドコードを書くとエラーにならず、その項目だけ空欄でレコードが登録されます。一覧の取得は1回500件までで、「全件取って、無ければ督促する」作りは打ち切りに気づかず誤判定します。運用しているn8nでこれを踏み、督促が数十件誤って飛んだことがあります。アプリの作り方やAPIトークンの権限は、姉妹サイトのkintone自作ガイドに書いています。
例:Salesforceにリードとして登録する
Salesforceには専用ノードがあります。「Resource」を「Lead」、「Operation」を「Create」にして、会社名・氏名・メールを割り当てます。接続はCredentialで「OAuth2」を選び、Salesforce側はアプリケーションマネージャーの「New External Client App」で作ります。コールバックURLにn8nのOAuthのURLを入れ、スコープに「Full access (full)」と「Perform requests at any time (refresh_token, offline_access)」を足します。従来のConnected Appは廃止に向かっています。本番かSandboxかはCredentialの「Environment Type」で選びます。項目設計や権限は、姉妹サイトのSalesforce自作ガイドに書いています。

n8n自体のAPIで外から操作する
n8nのPublic API(REST API)で、ワークフローの一覧を取る、公開を切り替える、実行履歴を見る、ができます。セルフホストはどの版でも、n8n Cloudは有料プランで使え、無料トライアルでは使えません。
- 「Settings」の「n8n API」を開き、「Create API key」を押す。
- 「Label」に用途を入れ、「Expiration」で期限を決め、「Scopes」で範囲を選ぶ。
- 表示されたキーをパスワード管理ツールに保存する。

キーは X-N8N-API-KEY ヘッダーで送ります。下は公開中のワークフロー一覧と、エラーで終わった実行の一覧を取る例です。1回100件、limit で最大250件まで返り、続きは返事の nextCursor を cursor= に付けて取ります。
curl -s 'https://n8n.example.co.jp/api/v1/workflows?active=true&limit=250' \
-H "X-N8N-API-KEY: $N8N_API_KEY"
curl -s 'https://n8n.example.co.jp/api/v1/executions?status=error&limit=100' \
-H "X-N8N-API-KEY: $N8N_API_KEY"
| やりたいこと | メソッドとパス |
|---|---|
| 一覧・1本の中身 | GET /api/v1/workflows・/api/v1/workflows/{id} |
| 公開する・やめる | POST /api/v1/workflows/{id}/publish・/unpublish |
| 実行履歴 | GET /api/v1/executions(status・workflowId・includeData) |
| 失敗した実行をやり直す | POST /api/v1/executions/{id}/retry |
1.x の /activate は非推奨で /publish に置き換わりました。ワークフローを外から「今すぐ実行」するエンドポイントは無いので、外から動かしたいワークフローは先頭をWebhookにします。
APIキーの「Scopes」は「All」(全部)、「Read only」(読むだけ)、「Custom」(選んだ権限だけ)から選べます。一覧を取るだけなら「Read only」にし、「All」は作った人の権限を全部持つので管理者のパスワードと同じ扱いにします。用途ごとにキーを分けます。PUT /api/v1/workflows/{id} はワークフロー全体を置き換えるので、手元のJSONが古いと画面で直した分が巻き戻ります。送る前に本番との差分を見ます。使わないなら、セルフホストは N8N_PUBLIC_API_DISABLED=true でAPIごと止められます。
応用
よく使うサービスのつなぎ方
| サービス | つなぎ方 | 押さえどころ |
|---|---|---|
| Slack | 専用ノード(Send) | 送るだけならボットのトークンで足りる。検索はユーザーのトークンが要る |
| Googleスプレッドシート | 専用ノード(Append Row) | 「Map Automatically」で項目名と列名が同じものを自動で入れる |
| Notion | 専用ノード(Database Page の Create) | 書き込み先のページで「Connect to」から連携を追加しないとエラー |
| Discord | 専用ノード(Message の Send) | 「Send and Wait for Response」で返事も待てる |
スプレッドシートの行を更新するときは、日時のような値を照合のキーにしません。運用しているn8nで、同じ日時の行が2つあったため別の行を上書きし続け、3か月以上予定の処理が1件も動かなかったことがあります。公式ドキュメントには載っていませんが、更新系の操作では照合する列にn8nが付ける row_number を選べるので、行の特定にはこれを使います。
時間のかかる処理は先に返事をする
つなぐ処理が増えるほど返事は遅れます。n8n Cloudでは100秒以内に返事をしないと524で切られます。「Respond」を「Immediately」にするか、Respond to WebhookをWebhookの直後に置いて先に返し、重い処理はその後ろで続けます。
送ってきた相手を署名で確かめる
署名を付けて送ってくるサービスは、HMACを計算して確かめます。Codeノードの require('crypto') は、n8n Cloudと、セルフホストの導入記事で組んだ外部モード(task-runners を別に立てる構成)なら最初から使えます。npx n8n などで外部モードにしていない場合は、組み込みモジュールを許可する設定(NODE_FUNCTION_ALLOW_BUILTIN)を足さないと落ちます。どちらでも動くように、運用しているn8nでは計算を「Crypto」ノードに任せ、Codeノードでは比べるだけにしています。
できないことと、その代わり
| できないこと | 代わりの手 |
|---|---|
| Public APIでワークフローを今すぐ実行する | 先頭をWebhookにしてHTTPで呼ぶ |
| 同じPathとメソッドで2本のWebhookを置く | Pathを分ける |
| Webhookで16MiBを超えるデータを受ける | セルフホストは N8N_PAYLOAD_SIZE_MAX で上げる。ファイルはストレージに置いてURLだけ送る |
よく詰まるところ
| 症状 | 原因 | 直し方 |
|---|---|---|
| Test URLでは動いたのに、フォームから送ると404 | 公開していない、またはURLが webhook-test のまま | 公開して、URLを webhook に直す |
Webhookノードに出るURLが localhost | 外向きのURLを教えていない | 環境変数 N8N_WEBHOOK_URL=https://n8n.example.co.jp/ を入れて再起動(旧名 WEBHOOK_URL は2.35.0から非推奨) |
| 後ろのノードで会社名が空 | $json.company と書いている | $json.body.company にする |
| Slackに同じ通知が何十回も飛ぶ | 配列が分かれてアイテムが増えた | 通知ノードの「Execute Once」をオンにする |
| 「The value in the “JSON Body” field is not valid JSON」 | 本文の " や改行でJSONが壊れた | 値を {{ JSON.stringify(...) }} で包む |
| 日本語が文字化けする | 送信側が文字コードを付けていない | Content-Type: application/json; charset=utf-8 で送る |
| 429が返る | 相手のレート制限 | Batchingで間隔を空け、Retry On Failを足す |
| n8n Cloudで524が返る | 100秒以内に返事をしていない | 先に返事を返し、重い処理は後ろに回す |
| 「Connection refused (ECONNREFUSED)」 | Dockerの中から localhost を呼んでいる | 同じComposeのサービス名で呼ぶ。ホスト側は host.docker.internal(Linuxは extra_hosts に host.docker.internal:host-gateway を足す) |
| 403「Forbidden – perhaps check your credentials」 | 権限やスコープが足りない | スコープを見直す。Notionはページに連携を追加する |
| 2ページ目以降が取れない | ページ送りの指定が仕様と違い、黙って無視されている | APIドキュメントどおりの場所に書く |
| 0件のはずが実は取りこぼしていた | 上限で打ち切られた、またはContinueで失敗が空の結果になった | 件数が上限ちょうどなら警告を出す。失敗はエラー用の出口に流す |

詰まったら、Executionsタブで該当の実行を開き、ノードごとの件数と最後に動いたノードを見ます。