Webhook

双方向ではない、一方的な通知投稿のための仕組み。Bot を作らなくても URL に POST するだけで Discord にメッセージを送れる。 CI 通知・監視アラート・GitHub 連携の定番。

使いどころ

1. Webhook URL の作り方

サーバー設定から

  1. チャンネルの設定(歯車)→ 連携サービスWebhook
  2. 「新しいウェブフック」→ 名前・アイコンを設定
  3. 「ウェブフック 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")

レート制限

セキュリティ

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 を登録すると有効化。