n8n×LINE APIで問い合わせを自動分類・担当通知する
n8nとLINE APIを連携し、顧客問い合わせをキーワード自動分類して担当チームへSlack通知する手順を解説します。
はじめに
LINEは国内で9,600万人以上が利用するメッセージングプラットフォームです。 多くの企業がLINE公式アカウントを通じて顧客と接点を持っていますが、問い合わせ対応は依然として手作業に頼るケースが多く、担当者の負担になっています。 本記事では、n8nとLINE Messaging APIを組み合わせ、顧客からの問い合わせメッセージをキーワードで自動分類し、適切な担当チームへSlack通知を送る仕組みを構築します。 さらに、問い合わせを受け付けた旨をLINEへ自動返信することで、顧客体験の向上も同時に実現します。
このシステムで実現できること
n8n×LINE Messaging APIの連携で、以下の一連の処理が完全自動化されます。
顧客がLINE公式アカウントへメッセージを送信すると、LINE PlatformからWebhookでn8nにイベントが届きます。 n8nはメッセージのテキストを解析し、「技術的な問い合わせ」「料金・請求」「一般的な問い合わせ」などのカテゴリへ分類します。 分類結果に応じて対応するSlackチャンネルへ問い合わせ内容と差出人情報を通知し、担当者がSlackを見るだけで即座に内容を把握できる状態を作ります。 同時に、LINE Reply APIで受付確認メッセージを顧客へ自動送信します。
この仕組みを導入することで、問い合わせの見落とし防止・対応開始までの時間短縮・担当部署への自動振り分けが実現します。
事前準備
LINE Developersでの設定
- LINE Developers Console にログインし、プロバイダーとチャネル(Messaging API)を作成します。
- チャネル基本設定から Channel Secret をコピーしておきます。
- Messaging API設定タブから Channel Access Token(長期) を発行してコピーします。
- Webhook URLは、後ほどn8nが生成するURLを貼り付けます。
n8nのDockerセットアップ
n8nをDockerで起動します。 環境変数にタイムゾーンを指定することで、ログのタイムスタンプが日本時間で表示されます。
docker run -d \
--name n8n \
-p 5678:5678 \
-e N8N_TIMEZONE=Asia/Tokyo \
-e TZ=Asia/Tokyo \
-v n8n_data:/home/node/.n8n \
docker.n8n.io/n8nio/n8n
起動後、http://localhost:5678 にアクセスしてアカウントを作成します。
次に「Settings → n8n API → Environment Variables」から以下の変数を登録してください。
LINE_CHANNEL_SECRET:LINE Developersで取得したChannel SecretLINE_CHANNEL_ACCESS_TOKEN:発行したChannel Access Token(長期)SLACK_WEBHOOK_URL:Slack Incoming Webhook URL
Slackの設定
Slack API(https://api.slack.com/apps)でアプリを作成し、Incoming Webhookを有効化します。 「技術サポート」「料金・請求」「一般問い合わせ」の3チャンネルを用意し、それぞれのWebhook URLを控えておきます。
ワークフロー構築:5ステップ
n8nのワークフローは5つのノードで構成されます。
Step 1:Webhookノードでイベントを受信する
n8nで新規ワークフローを作成し、最初のノードとして Webhook を追加します。
- HTTP Method:POST
- Path:
line-webhook(任意の文字列) - Authentication:None(署名検証はCodeノードで実装)
- Response Mode:Respond to Webhook
ノードを保存するとTest URLが生成されます。 このURLをLINE DevelopersコンソールのWebhook URLに貼り付け、「Verify」ボタンで疎通確認してください。
Step 2:Codeノードで署名を検証する
LINEのWebhookリクエストには、正当性を確認するための署名ヘッダー x-line-signature が付与されます。
この検証を省略すると、第三者が偽のWebhookを送り付ける攻撃を受けるリスクがあります。
Webhookノードの次に Code ノードを追加し、以下のコードを記述してください。
const crypto = require('crypto');
const channelSecret = $env.LINE_CHANNEL_SECRET;
const rawBody = $json.body ? JSON.stringify($json.body) : '';
const signature = ($json.headers && $json.headers['x-line-signature']) || '';
const hash = crypto
.createHmac('SHA256', channelSecret)
.update(rawBody, 'utf8')
.digest('base64');
if (hash !== signature) {
throw new Error('Invalid LINE signature. Request rejected.');
}
const events = ($json.body && $json.body.events) ? $json.body.events : [];
return events
.filter(event => event.type === 'message' && event.message.type === 'text')
.map(event => ({
json: {
replyToken: event.replyToken,
userId: event.source.userId,
messageText: event.message.text,
timestamp: new Date(event.timestamp).toISOString(),
}
}));
$env.LINE_CHANNEL_SECRET はn8nのEnvironment Variablesから参照されます。
署名が一致しない場合はエラーをスローし、後続ノードの実行を停止します。
テキスト以外のメッセージ(スタンプ・画像など)はこの段階でフィルタリングされます。
Step 3:Codeノードでメッセージを分類する
次の Code ノードで、メッセージテキストをキーワードマッチングにより分類します。 ビジネス要件に合わせてキーワードのリストを拡張してください。
const text = $input.first().json.messageText || '';
const rules = [
{
category: 'technical',
label: '技術的な問い合わせ',
slackChannel: '#support-technical',
keywords: ['エラー', '不具合', 'バグ', '動かない', '接続できない', 'ログインできない', 'クラッシュ'],
},
{
category: 'billing',
label: '料金・請求に関する問い合わせ',
slackChannel: '#support-billing',
keywords: ['料金', '請求', '支払い', '領収書', '解約', 'キャンセル', 'プラン', '返金'],
},
];
const matched = rules.find(rule =>
rule.keywords.some(kw => text.includes(kw))
) || {
category: 'general',
label: '一般的な問い合わせ',
slackChannel: '#support-general',
};
const input = $input.first().json;
return [{
json: {
category: matched.category,
categoryLabel: matched.label,
slackChannel: matched.slackChannel,
replyToken: input.replyToken,
userId: input.userId,
messageText: input.messageText,
timestamp: input.timestamp,
}
}];
rules 配列にカテゴリ定義を追加するだけでルーティング先を柔軟に拡張できます。
キーワードに一致しないメッセージはデフォルトの general チャンネルへルーティングされます。
Step 4:HTTP RequestノードでSlackへ通知する
HTTP Request ノードを追加し、以下の設定でSlack Incoming WebhookへPOSTします。
- Method:POST
- URL:
{{ $env.SLACK_WEBHOOK_URL }} - Body Type:JSON
JSON Bodyには、Slackの attachments 形式で問い合わせの詳細を含めます。
color フィールドにカテゴリ別の色コードを設定することで、通知一覧を一目で把握できます。
fields には userId・categoryLabel・messageText・timestamp の4フィールドを含めることを推奨します。
Step 5:HTTP RequestノードでLINEへ自動返信する
最後に HTTP Request ノードを追加し、LINE Reply Message APIを呼び出します。
- Method:POST
- URL:
https://api.line.me/v2/bot/message/reply - Header:
Authorization: Bearer {{ $env.LINE_CHANNEL_ACCESS_TOKEN }} - Body Type:JSON
JSON Bodyは以下の形式で指定します。
{
"replyToken": "{{ $json.replyToken }}",
"messages": [
{
"type": "text",
"text": "お問い合わせありがとうございます。\n担当スタッフが内容を確認後、あらためてご連絡いたします。\n今しばらくお待ちください。"
}
]
}
replyToken は受信イベントごとに発行される使い捨てのトークンで、受信から1分以内に使用する必要があります。
n8n全体の処理は通常数秒以内に完了するため、タイムアウトは実運用上ほとんど問題になりません。
運用ポイント
Webhookを本番環境へ切り替える
n8nのWebhookノードには「Test URL」と「Production URL」の2種類があります。 テスト中はTest URLを使いますが、ワークフローを Active にしてProduction URLに切り替えない限り、実際のLINEイベントは受信されません。 ワークフロー右上の Active トグルをオンにして、LINE DevelopersのWebhook URLをProduction URLへ更新することを忘れないでください。
エラー通知を設定する
n8nには Error Trigger ノードが用意されています。 署名検証の失敗やSlack API障害など、予期せぬエラーが発生した場合に別チャンネルへ通知するサブワークフローを作成しておくと、問題の早期発見につながります。 少なくとも「Settings → Log Level: info」を有効化し、エラーログを残す設定を入れておきましょう。
大量受信時のレート制限
同時に多数のWebhookが届く場合は、n8nのWebhookノード設定「Options → Rate Limit」でリクエスト頻度を制御できます。 また、LINE Platform側のWebhookタイムアウトはデフォルト10秒のため、Slackへの通知処理が長引く場合は非同期化を検討してください。
発展応用
今回のキーワードマッチングは実装がシンプルな一方、表現のゆらぎへの対応が難しいという弱点があります。
AIによる自然言語分類 Step 3のCodeノードでキーワードマッチングの代わりにClaude APIやOpenAI APIを呼び出すことで、「先日購入したものが壊れた」のような間接的な表現も正確に分類できます。 HTTP Requestノードを追加してAPIを呼び出し、レスポンスのカテゴリ文字列をそのままルーティングに使うだけで切り替えが完了します。
Notionへの問い合わせ記録 Slack通知に加え、Notionの公式ノードを使って問い合わせ内容をデータベースへ自動記録することで、対応履歴の管理が容易になります。
まとめ
本記事では、n8n×LINE Messaging APIで顧客問い合わせを自動分類・担当通知するワークフローの構築手順を解説しました。
- Codeノードで HMAC-SHA256 署名を検証し、なりすまし攻撃を防ぐ
- キーワードマッチングで問い合わせをカテゴリ分類し、適切なSlackチャンネルへルーティングする
- LINE Reply APIで受付確認メッセージを自動送信し、顧客体験を向上させる
この仕組みにより、問い合わせの振り分け作業がゼロになり、担当者への通知が即時化されます。 まずはDockerでn8nを立ち上げ、テスト環境でWebhookの疎通から確認してみてください。