Webhook
双方向ではない、一方的な通知投稿のための仕組み。Bot を作らなくても URL に POST するだけで Discord にメッセージを送れる。 CI 通知・監視アラート・GitHub 連携の定番。
使いどころ
- CI / CD の通知(ビルド成功 / テスト失敗)
- サーバ監視(ダウン検知、エラー多発)
- GitHub 連携(PR・Issue の通知 — GitHub には組み込みあり)
- 外部サービス → Discord(Zapier / Make / 自前スクリプト)
- cron で定期投稿
1. Webhook URL の作り方
サーバー設定から
- チャンネルの設定(歯車)→ 連携サービス → Webhook
- 「新しいウェブフック」→ 名前・アイコンを設定
- 「ウェブフック URL をコピー」
Bot から作る
const channel = await client.channels.fetch(CHANNEL_ID)
const webhook = await channel.createWebhook({
name: "通知 Bot",
avatar: "https://example.com/icon.png",
})
console.log(webhook.url)
2. URL に POST するだけ
Bot トークン不要。URL を持っている人なら誰でも送信できる。
curl
curl -X POST "$WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d '{"content": "Hello from curl"}'
fetch(Node.js / ブラウザ)
await fetch(WEBHOOK_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ content: "Hello" }),
})
送信できる payload
{
"content": "本文",
"username": "上書き表示名",
"avatar_url": "https://...",
"embeds": [
{
"title": "タイトル",
"description": "説明",
"color": 5814783,
"fields": [
{ "name": "項目", "value": "値", "inline": true }
],
"thumbnail": { "url": "https://..." },
"image": { "url": "https://..." },
"footer": { "text": "footer" },
"timestamp": "2026-05-10T12:00:00Z"
}
],
"tts": false,
"allowed_mentions": { "parse": [] }
}
discord.js から扱う
import { WebhookClient, EmbedBuilder } from "discord.js"
const wh = new WebhookClient({ url: WEBHOOK_URL })
await wh.send({
content: "デプロイ完了",
username: "CI",
avatarURL: "https://example.com/ci.png",
embeds: [
new EmbedBuilder()
.setTitle("v1.2.3 をリリース")
.setURL("https://example.com/release/1.2.3")
.setColor(0x00ff00)
.addFields({ name: "コミット", value: "abc1234" }),
],
})
ファイル添付
await wh.send({
content: "ログ",
files: [
new AttachmentBuilder("./error.log").setName("error.log"),
],
})
編集・削除
Webhook で送ったメッセージはその Webhook 経由で編集・削除可能。返り値を保持しておく。
const sent = await wh.send({ content: "ビルド中..." })
// ... 進捗
await wh.editMessage(sent.id, { content: "ビルド完了!" })
await wh.deleteMessage(sent.id)
実用例
GitHub Actions から通知
.github/workflows/notify.yml
- name: Notify Discord
if: always()
run: |
STATUS="${{ job.status }}"
COLOR=$([ "$STATUS" = "success" ] && echo 65280 || echo 16711680)
curl -X POST "${{ secrets.DISCORD_WEBHOOK }}" \
-H "Content-Type: application/json" \
-d "{\"embeds\":[{\"title\":\"$STATUS\",\"color\":$COLOR}]}"
監視アラート
async function alert(message: string, severity: "info" | "warn" | "error") {
const color = { info: 0x3498db, warn: 0xf39c12, error: 0xe74c3c }[severity]
await fetch(WEBHOOK_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
embeds: [{
title: severity.toUpperCase(),
description: message,
color,
timestamp: new Date().toISOString(),
}],
}),
})
}
await alert("DB connection lost", "error")
レート制限
- 1 Webhook あたり2 秒で 5 リクエスト(バースト)
- 同一 Webhook に大量送信すると 429 が返る
- discord.js の
WebhookClientは自動でキューイングするので普通の使用では問題ない - cron で大量バルク投稿する時は明示的に sleep
セキュリティ
- Webhook URL = フルアクセス権。Git に commit しない、シークレットマネージャ経由で渡す
- 漏れたらすぐに削除して作り直す(チャンネル設定から)
- クライアント JS から呼ぶ場合はサーバ経由に。直接 URL を出すと誰でも投稿できる
- Rate limit に当てて荒らされる可能性も。投稿元 IP 等は記録しておく
HTTP Interactions(サーバレス Bot)
Webhook と似ているが逆方向: Discord → サーバへ POST。 Cloudflare Workers / Vercel / Lambda 等で常時稼働なしに Bot が作れる。
// Cloudflare Workers の例
import { verifyKey } from "discord-interactions"
export default {
async fetch(req: Request, env: Env) {
const sig = req.headers.get("X-Signature-Ed25519")!
const ts = req.headers.get("X-Signature-Timestamp")!
const body = await req.text()
const valid = verifyKey(body, sig, ts, env.DISCORD_PUBLIC_KEY)
if (!valid) return new Response("invalid", { status: 401 })
const interaction = JSON.parse(body)
if (interaction.type === 1) { // PING
return Response.json({ type: 1 })
}
if (interaction.type === 2) { // APPLICATION_COMMAND
return Response.json({
type: 4,
data: { content: "Hello from Worker!" },
})
}
},
}
Discord Developer Portal → "Interactions Endpoint URL" にデプロイ先 URL を登録すると有効化。