LINE公式アカウントに届いたメッセージをn8nで受け、Googleスプレッドシート「問い合わせ一覧」に1行足し、Slackの #問い合わせ に知らせ、お客様には受付の返事を返します。「問い合わせ受付」にLINEという入口を1つ足す作業で、LINE側の設定から署名の検証、返信、料金の見積もりまで通します。前提は、n8n 2.44.7(2026年10月時点の安定版)が n8n.example.co.jp のような独自ドメインとHTTPSで動いていることです。WebhookとHTTP Requestの基本は「n8nで外部サービスとつなぐ:Webhook・HTTP Request・API」に任せ、LINE固有の部分に絞ります。
先に決めること
LINE Notifyの代わりをどれにするか
LINE Notifyは2025年3月31日でサービスを終えました。n8nの「Line」ノードはこのLINE Notify用で、2.44.7ではノードの一覧にも出ず、古いワークフローに残っていても何も届きません。LINEで知らせるなら、LINE公式アカウントを作ってMessaging APIで送ります。LINEヤフーもこれを代わりとして案内しています。
ただ、社員への通知に使っていたのなら、移り先をLINEにこだわる必要はありません。Messaging APIのプッシュ送信は通数で料金が決まり、社内向けに使うと無料の枠をすぐ使い切ります。
| 移り先 | 費用 | 向いている使い方 |
|---|---|---|
| Slack(#問い合わせ) | 何件送っても同じ | 社内への通知の本命。この記事の例 |
| 社員のLINEグループへプッシュ | 1回でグループの人数分の通数 | Slackを使っていない少人数の会社 |
| 当番1人へプッシュ | 1回1通 | 夜間・休日の当番だけに知らせる |
| Gmail | 追加の費用なし | 通知を記録として残したい |
社内はSlack、お客様とはLINE、と分けるのが一番安く済みます。
お客様に返すのは「応答」、こちらから送るのは「プッシュ」
送り方は5種類あり、問い合わせ受付で使うのは2つです。
| 応答メッセージ(reply) | プッシュメッセージ(push) | |
|---|---|---|
| いつ送るか | お客様からメッセージが来た直後 | いつでも |
| 送り先の指定 | Webhookで届いた応答トークン | ユーザーID・グループID |
| 期限 | 受信から1分以内に、1回だけ | なし |
| 通数(料金) | 数えない | 数える |
| エンドポイント | POST https://api.line.me/v2/bot/message/reply | POST https://api.line.me/v2/bot/message/push |
受付の返事は必ず応答で返します。
料金はプッシュの通数で決まる
LINE公式アカウントの料金プランは次の3つです(2026年10月時点、日本のプラン、金額は税別)。
| プラン | 月額固定費 | 無料メッセージ通数(月) | 追加メッセージ |
|---|---|---|---|
| コミュニケーションプラン | 0円 | 200通 | 不可 |
| ライトプラン | 5,000円 | 5,000通 | 不可 |
| スタンダードプラン | 15,000円 | 30,000通 | 可(従量課金。単価は送信数で変わる) |
追加メッセージの単価は2026年10月1日に改定されたので、LINEヤフーの料金ページで確かめます。開設したときはコミュニケーションプランです。通数は「送信対象になった人数」で数え、1回に吹き出しを何個入れても変わりません。公式の例では、4件入れたプッシュを5人いるトークルームに1回送ると5通です。ブロックしている相手に送った分は数えません。
数えるのはプッシュ・マルチキャスト・ブロードキャスト・ナローキャストで、応答メッセージと、LINE Official Account Managerのチャットで担当者が手で返す分は数えません。社員5人のグループに新着を知らせると1件5通なので、200通では月40件で止まります。上限を超えると送信は429で失敗します。コミュニケーションプランとライトプランは追加メッセージを買えないので、超えそうならプランを上げます。
n8nを外から届くURLで動かす
LINEのWebhookは、認証局の証明書を使ったHTTPSのURLにしか送られません。自己署名の証明書は使えず、手元のPCのn8nにも届かないので、n8n CloudかVPSに立てたn8nで組みます。立て方は「n8nをセルフホストで導入する:Docker ComposeでVPSに立て、独自ドメインとHTTPSで使う」に書いています。
作るものの一覧
| ノード(名前) | 役割 | 主な設定 |
|---|---|---|
| Webhook(LINE受信) | LINEからの通知を受ける | POST、Path: line、Immediately、Raw Body |
| Crypto(署名を計算) | 署名を計算する | Hmac、SHA256、BASE64 |
| If(署名が一致) | 届いた署名と比べる | x-line-signature |
| Split Out(イベントごとに分ける) | イベントを1件ずつにする | body.events |
| Remove Duplicates(再送を捨てる) | 二重処理を防ぐ | webhookEventId |
| Filter(テキストだけ通す) | 1対1のテキストだけ残す | type・message.type・source.type |
| HTTP Request(プロフィールを取る) | 表示名を取る | GET /v2/bot/profile/{userId} |
| Edit Fields (Set)(LINE用に整える) | シートの列に合わせる | 受付日時・お名前・内容ほか |
| HTTP Request(受付の返事) | 応答メッセージを返す | POST /v2/bot/message/reply |
| Google Sheets | 「問い合わせ一覧」に1行足す | Append Row |
| Slack | #問い合わせ に知らせる | Send a message |

LINE側の準備
LINE公式アカウントを作り、Messaging APIを有効にする
2024年9月4日から、LINE DevelopersコンソールでMessaging APIのチャネルを直接は作れなくなりました。先にLINE公式アカウントを作り、そのアカウントでMessaging APIを有効にすると、チャネルが自動でできます。
- LINEヤフーの「ビジネスID」に登録し、続けて出る作成フォームでLINE公式アカウントを作る。
- LINE Official Account Managerで作ったアカウントを開く。
- 「設定」の「Messaging API」で「Messaging APIを利用する」を押す。
- 開発者情報を求められたら名前とメールアドレスを入れる。
- プロバイダーを選ぶか新しく作り、「同意する」、確認画面で「OK」を押す。
- 同じアカウントでLINE Developersコンソールに入り、チャネルができていることを確かめる。
プロバイダーは後から変えられません。違うプロバイダーでは同じ人でもユーザーIDが変わるので、会社名のプロバイダー1つにまとめ、制作会社やツール業者のプロバイダーの下には作りません。
チャネルシークレットとチャネルアクセストークン
n8nに渡す鍵は2つです。取り違えると署名が合わないか、送信が401で落ちます。
| 鍵 | 場所 | n8nでの使い道 | 入れるCredential |
|---|---|---|---|
| チャネルシークレット | 「チャネル基本設定」タブ | 届いた通知の署名を計算する | Crypto の「Hmac Secret」 |
| チャネルアクセストークン(長期) | 「Messaging API設定」タブで発行 | 返信・送信のAPIを呼ぶ | Bearer Auth の「Bearer Token」 |
トークンには、v2.1(期限を自分で決める・最長30日)、短期(30日)、ステートレス(15分)、長期(期限なし)があります。v2.1は発行にJWTの署名が要り、期限(最長30日)ごとに作り直す仕組みを自分で持つことになります。問い合わせ受付なら長期のトークンで回ります。長期は1チャネルに1つで、再発行すると今のトークンは止まります。漏れると全部の友だちに一斉送信されかねないので、n8nのCredential以外には置きません。Credentialの共有は「n8nの認証情報(Credential):OAuth2・APIキー・共有と権限」に書いています。
応答メッセージとあいさつメッセージを切る
最初から「応答メッセージ」(決まった文の自動返信)と「あいさつメッセージ」(友だち追加のお礼)がオンです。応答メッセージを残すと、n8nの返事と二重に届きます。
- 「Messaging API設定」タブで「応答メッセージ」の「編集」を押す。
- 開いた「設定」>「応答設定」で、応答メッセージをオフにする。
- あいさつメッセージは、出したいなら残す。
2022年12月から、チャットとWebhookは同時に使えます。担当者がチャットで手で返す運用と、n8nでの記録・通知は両立します。
n8nで受ける
Webhookノード
- 新しいワークフローを作り、名前を「LINE問い合わせ受付」にする。
- 最初のノードに「Webhook」を置き、名前を「LINE受信」にする。
- 「HTTP Method」を
POST、「Path」をlineにする。 - 「Authentication」は「None」のままにする。
- 「Respond」を「Immediately」(すぐに返事をする)にする。
- 「Add Option」から「Raw Body」を足してオンにする。
- 「Add Option」から「Only Run If」を足し、
{{ $json.body.events.length > 0 }}を入れる。

LINEは2秒以内に返事が無いとタイムアウトとして扱うので、後ろを待たずに200を返す「Immediately」にします。LINEは自分で決めたヘッダーを付けられず、送信元IPアドレスも公開していないので、Header Authや「IP(s) Allowlist」を掛けると全部弾かれます。守りは署名の検証が担います。
「Raw Body」は、届いたままの本文をバイナリの data に残すオプションです。署名は届いた文字列そのものから計算する決まりで、読み取ったJSONを文字列に戻すと空白やエスケープが変わって一致しません。
「Only Run If」は、式が true のときだけ動かすオプションです。LINEは疎通確認に "events": [] だけの通知を送ることがあります。この式で、空の通知は200を返すだけで実行履歴にも残りません。
署名を確かめる
届いた通知の x-line-signature ヘッダーには、本文をチャネルシークレットでHMAC-SHA256にかけ、Base64にした値が入っています。同じ計算をして一致したものだけ通します。
- 「LINE受信」の後ろに「Crypto」を置き、名前を「署名を計算」にする。
- 「Action」を「Hmac」にする。
- 「Binary File」をオンにし、「Binary Property Name」を
dataにする。 - 「Type」を「SHA256」にする。
- 「Property Name」を
signatureにする。 - 「Encoding」を「BASE64」にする(初期値はHEX)。
- Credentialで「Crypto」を新しく作り、「Hmac Secret」にチャネルシークレットを入れる。
- 後ろに「If」を置き、名前を「署名が一致」にする。
- 条件の左に
{{ $json.signature }}、比べ方に「String」の「is equal to」、右に{{ $json.headers['x-line-signature'] }}を入れる。 - 「true」の出口だけ次につなぎ、「false」の出口には何もつながない。

ヘッダー名はn8nの中では小文字で入るので、X-Line-Signature ではなく小文字で参照します。Codeノードでも書けますが、セルフホストでは組み込みモジュール crypto を許可する設定が要ります。Cryptoノードなら設定なしで動き、シークレットもCredentialに収まります。
先に200を返しているので、署名が合わない通知も送り主からは成功に見えます。偽の通知でシートやSlackが動かなければ足ります。
手元から署名つきで送って試す
スマートフォンの前に、curlで署名つきの通知を送って確かめます。「Listen for test event」を押して120秒以内に送ります。
SECRET='チャネルシークレットをここに'
BODY='{"destination":"U0","events":[{"type":"message","timestamp":1793000000000,"source":{"type":"user","userId":"U1"},"webhookEventId":"TEST001","replyToken":"dummy","message":{"type":"text","text":"料金表を送ってください"}}]}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -binary | openssl base64)
curl -X POST 'https://n8n.example.co.jp/webhook-test/line' \
-H 'Content-Type: application/json' \
-H "x-line-signature: $SIG" \
--data-binary "$BODY"
「署名が一致」の true 側に出れば合っています。SECRET を1文字変えて false 側に落ちることも確かめます。応答トークンが偽物なので「受付の返事」は400で失敗しますが、そこまで来ていれば正常です。2回目は「再送を捨てる」で止まるので、webhookEventId を変えて送ります。
LINE側でWebhook URLを登録して検証する
- n8nでワークフローを公開(Publish)する。
- LINE Developersコンソールでチャネルを開き、「Messaging API設定」タブを開く。
- 「Webhook URL」の「編集」を押し、
https://n8n.example.co.jp/webhook/lineを入れて「更新」を押す。 - 「検証」を押し、「成功」と出ることを確かめる。
- 「Webhookの利用」をオンにする。
- 「Webhookの再送」をオンにする(注意事項が出るので読んでから)。
- 「エラーの統計情報」をオンにする。
- 同じタブのQRコードを自分のスマートフォンで読み、友だち追加する。
「検証」で送られるのは events が空の通知で、「Only Run If」で止まるので実行履歴は空のままです。中身はスマートフォンから確かめます。
「Webhookの再送」をオンにすると、n8nが止まっていた間の通知も復旧後に届くことがあります(回数と間隔は非公開で、保証はありません)。再送は deliveryContext.isRedelivery 以外は元と同じで、webhookEventId も変わらないので、これで重複を除けます。「エラーの統計情報」をオンにすると「Webhookエラー」タブに、n8nに届く前の失敗(接続できない、2秒以内に返事が無いなど)が残ります。
イベントを1件ずつに分ける
- 「署名が一致」の true の後ろに「Split Out」を置き、名前を「イベントごとに分ける」にする。「Fields To Split Out」は
body.events。 - 後ろに「Remove Duplicates」を置き、名前を「再送を捨てる」にする。「Operation」は「Remove Items Processed in Previous Executions」、「Keep Items Where」は「Value Is New」、「Value to Dedupe On」は
{{ $json.webhookEventId }}。 - 後ろに「Filter」を置き、名前を「テキストだけ通す」にする。条件は3つで、すべて「is equal to」。
{{ $json.type }}がmessage、{{ $json.message.type }}がtext、{{ $json.source.type }}がuser。

1回の通知に複数のイベントが入ることがあるので分けます。Filterで落ちるのは友だち追加(follow)、ブロック(unfollow)、スタンプや画像、グループでの発言です。画像も記録したいなら、Filterの代わりに「Switch」で message.type ごとに分けます(「n8nの分岐とループ:IF・Switch・Merge・Loop Over Items」)。
返信と送信をHTTP Requestで
HTTP Requestの認証は、どれも「Authentication」を「Generic Credential Type」、「Generic Auth Type」を「Bearer Auth」にし、チャネルアクセストークンのCredentialを選びます。
プロフィールで表示名を取る
- 「テキストだけ通す」の後ろに「HTTP Request」を置き、名前を「プロフィールを取る」にする。
- 「Method」は
GET、「URL」はhttps://api.line.me/v2/bot/profile/{{ $json.source.userId }}。 - 「Settings」の「On Error」を「Continue」にする。
返ってくるのは displayName(表示名)・pictureUrl・statusMessage などで、電話番号やメールアドレスは取れません。友だちでない人やブロックした人などは404になりますが、問い合わせ自体は記録したいので止めずに続けます。
受け取った内容を整える
「プロフィールを取る」の後ろに「Edit Fields (Set)」を置き、名前を「LINE用に整える」にして、シートの列名に合わせた項目を作ります。
| 項目 | 値 |
|---|---|
| 受付日時 | {{ DateTime.fromMillis($('テキストだけ通す').item.json.timestamp).setZone('Asia/Tokyo').format('yyyy-LL-dd HH:mm') }} |
| お名前 | {{ $json.displayName ?? '(表示名を取得できず)' }} |
| 内容 | {{ $('テキストだけ通す').item.json.message.text }} |
| 経路 | LINE |
| LINEユーザーID | {{ $('テキストだけ通す').item.json.source.userId }} |
| replyToken | {{ $('テキストだけ通す').item.json.replyToken }} |
timestamp はミリ秒のUNIX時間で、再送でも元の発生時刻が入るので、遅れて届いても正しい時刻で残ります。式の書き方は「n8nの式(Expression)とデータの扱い:$json・ノードの参照・日付・JSON」に書いています。
応答メッセージで受付の返事を返す
- 「LINE用に整える」の後ろに「HTTP Request」を置き、名前を「受付の返事」にする。
- 「Method」は
POST、「URL」はhttps://api.line.me/v2/bot/message/reply。 - 「Send Body」をオンにし、「Body Content Type」を「JSON」、「Specify Body」を「Using JSON」にして下を入れる。
- 「Settings」の「Retry On Fail」はオフのままにする。
{
"replyToken": "{{ $json.replyToken }}",
"messages": [
{
"type": "text",
"text": "お問い合わせありがとうございます。内容を受け付けました。担当者から営業時間内にご連絡します。"
}
]
}

応答トークンは1回限りで、受信から1分以内に使う決まりです。なるべく早く使うよう求められているので、返事はシートやSlackより前に置きます。「Retry On Fail」を切るのは、1回目が届いていたときに2回目が「Invalid reply token」で落ちるからです。吹き出しは5つまでです。
プッシュで社員のグループに知らせる(Slackを使わない場合)
- 「Messaging API設定」タブの「グループトーク・複数人トークへの参加を許可する」を有効にする(初期値は無効)。
- 社員のLINEグループにLINE公式アカウントを招待する。
- 招待したときに届く参加イベント(
join)のsource.groupIdを、実行履歴の「イベントごとに分ける」の出力から控える。 - HTTP Requestの「URL」を
https://api.line.me/v2/bot/message/pushにし、本文のtoにそのグループIDを入れる。
1つのグループに入れるLINE公式アカウントは1つだけです。二重送信を防ぐ X-Line-Retry-Key は「n8nで外部サービスとつなぐ:Webhook・HTTP Request・API」に書いています。プッシュはブロックした相手にも200が返り、実際には届きません。
問い合わせ受付に組み込む
- 「問い合わせ一覧」の右端に「経路」「LINEユーザーID」の列を足す。フォーム側のワークフローは「経路」に
フォームを入れるように直す。 - 「受付の返事」の後ろに「Google Sheets」を置き、「Append Row」で「問い合わせ一覧」を選ぶ。
- 各列の値は、前のノードではなく「LINE用に整える」から取る。例: 「内容」は
{{ $('LINE用に整える').item.json['内容'] }}。「会社名」「メールアドレス」は空のまま、「対応状況」は未対応。 - 後ろに「Slack」の「Send a message」を置き、#問い合わせ を選んで下の本文を入れる。
LINEから問い合わせが届きました
お名前: {{ $('LINE用に整える').item.json['お名前'] }}
内容: {{ $('LINE用に整える').item.json['内容'] }}
返信はLINE Official Account Managerのチャットから
$json で参照しないのは、「受付の返事」を通ると中身がLINEの返事(sentMessages)に置き換わるからです。Slackの通知は「n8nとSlack連携:通知・投稿・ボタンで承認・スラッシュコマンド」に詳しく書いています。
LINEからは会社名もメールアドレスも取れないので、受付の返事でお願いするか、Webフォームへ案内します。2回目以降の返事は、担当者がチャットで手で返すのが通数もかからず確実です。
応用
AIで問い合わせの種類を振り分ける
「受付の返事」と「Google Sheets」の間にAI Agentノードを入れ、内容から「見積もり」「サポート」「その他」を選ばせて「種類」の列に入れます。返事を先に済ませておけば、AIが遅くても応答トークンの1分に引っかかりません。AIの答えをお客様に返すときは、POST https://api.line.me/v2/bot/chat/loading/start で1対1のトークにローディングのアニメーション(5〜60秒)を出せます。組み方は「n8nでAIエージェントを作る:ChatGPT・Claude・Geminiをつなぐ」に書いています。
通数の残りを毎朝見張る
Schedule Triggerで毎朝1回、次の2つをHTTP Requestで取り、使った割合が8割を超えたら #n8n-監視 に知らせます。
| 取るもの | エンドポイント | 返ってくる値 |
|---|---|---|
| 当月の上限目安 | GET https://api.line.me/v2/bot/message/quota | type(none か limited)と、limited のときだけ value |
| 当月に使った数 | GET https://api.line.me/v2/bot/message/quota/consumption | totalUsage |
利用状況の totalUsage は管理画面から手で配信した分を含む概算です。超えると月末まで通知が止まります。
できないことと、その代わり
| できないこと | 代わりの手 |
|---|---|
| LINE Notifyや旧「Line」ノードで通知する | Messaging APIのプッシュ。社内向けならSlackかGmail |
| LINE公式アカウントがいないトークのメッセージを受ける | 友だち追加かグループ招待をしてもらう |
| お客様の電話番号・メールアドレス・LINE IDを取る | 返事で聞くか、Webフォームへ案内する |
| 送信元IPアドレスや独自ヘッダーで送り主を絞る | 署名の検証で確かめる |
| 2秒を超える処理を終えてから返事をする | Webhookの「Respond」を「Immediately」にし、処理は後ろで続ける |
| 1分を過ぎてから応答メッセージで返す | プッシュで送る(通数を使う)か、チャットで手で返す |
| 無料・ライトプランで通数を超えて送る | スタンダードプランに上げる |
| 複数のLINE公式アカウントを1つのPathで受ける | シークレットが違うのでPathを分ける |
よく詰まるところ
| 症状 | 原因 | 直し方 |
|---|---|---|
| 「検証」が失敗する | 未公開、またはURLが webhook-test のまま | 公開し、URLを /webhook/line にする |
「検証」で TLS handshake failure | 自己署名の証明書か、中間証明書の不足 | 認証局の証明書と中間証明書を入れる |
| 「検証」で403 | Header AuthかIP(s) Allowlistを掛けている | 両方外す |
| 「検証」は成功するのに実行履歴が空 | 「Only Run If」で空の通知を止めている | 正常。スマートフォンから送って確かめる |
Webhookノードに出るURLが localhost | 外向きのURLを設定していない | N8N_WEBHOOK_URL=https://n8n.example.co.jp/ を入れて再起動 |
| 署名が一致しない | 「Raw Body」がオフで、読み取ったJSONから計算している | 「Raw Body」をオンにし、「Binary File」から計算する |
| 署名が一致しない(Raw Bodyはオン) | シークレットの取り違え・再発行、「Encoding」がHEX | シークレットを入れ直し、BASE64にする |
| 送信が401 | トークンの再発行、またはシークレットを入れた | Credentialを今のトークンに直す |
| 「Invalid reply token」 | 2回使った、1分を過ぎた | 返事を前に置き、「Retry On Fail」を切る |
| 返事が二重に届く | 応答メッセージがオンのまま | 応答設定でオフにする |
| シートに同じ行が2つ入る | 再送で同じイベントが2回届いた | webhookEventId で重複を捨てる |
| 429「You have reached your monthly limit.」 | 無料の通数を使い切った | 社内通知をSlackに移すか、プランを上げる |
| プッシュは200なのに届かない | ブロックされている | 200を届いた証拠にしない |
| プロフィールが404 | 友だちでない、ブロックされた、取得に同意していない | 「Continue」で表示名なしで記録する |
グループの発言で userId が無い | iOS版・Android版以外のLINEから送られた | グループIDだけで記録する |

詰まったらExecutionsタブでどのノードまで動いたかを見て、何も無ければLINE側の「Webhookエラー」タブを見ます。
次にやること
- n8nで外部サービスとつなぐ:Webhook・HTTP Request・API
- n8nとSlack連携:通知・投稿・ボタンで承認・スラッシュコマンド
- n8nをセルフホストで導入する:Docker ComposeでVPSに立て、独自ドメインとHTTPSで使う
- n8nでAIエージェントを作る:ChatGPT・Claude・Geminiをつなぐ
- n8nを止めずに運用する:アップデート・バックアップ・エラー通知・脆弱性