ブログに戻る
tutorial

日本企業の開示をリアルタイム通知:Webhook + Discord連携

Onkar Dahale

30分ごとにAPIを叩いて新着開示を確認する。レート制限を消費して、それでも気づくのは遅い。

Axioraのwebhookはこれを逆転させます。EDINETに新しい開示書類が提出されると、数分以内にあなたのURLにPOSTリクエストを送信。こちらから確認する必要はありません。

このチュートリアルでは、Discordチャンネルに通知を飛ばす仕組みをPython 40行で構築します。

Axiora Webhookの仕組み

3つのイベント:

イベント発火条件
new_filingEDINETから新しい有価証券報告書(年次・半期・四半期)が取り込まれたとき
amendment過去に提出された報告書の訂正報告書が公開されたとき
correction過去に提出された報告書の修正が公開されたとき

URLを登録し、受信するイベントを選択するだけ。各配信にはHMAC-SHA256署名が含まれるため、Axioraからの送信であることを検証できます。

HTTPS必須。タイムアウト10秒。失敗時は指数バックオフで2回リトライ(1秒、2秒)。合計3回試行。

ステップ1:Webhookを登録

curl -X POST https://api.axiora.dev/v1/webhooks \
  -H "Authorization: Bearer $AXIORA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-server.com/webhooks/axiora",
    "events": ["new_filing", "amendment"]
  }'

レスポンス:

{
  "data": {
    "id": "wh_8f2a3b...",
    "url": "https://your-server.com/webhooks/axiora",
    "events": ["amendment", "new_filing"],
    "secret": "a1b2c3d4e5f6...64文字の16進数..."
  }
}

secretを保存してください。作成時に一度だけ返されます。署名検証に必要です。

ステップ2:受信サーバーを構築

Webhookを受信し、署名を検証し、Discordに転送するFlaskサーバー:

import os
import hmac
import hashlib
import httpx
from flask import Flask, request, abort

app = Flask(__name__)

WEBHOOK_SECRET = os.environ["AXIORA_WEBHOOK_SECRET"]
DISCORD_WEBHOOK = os.environ["DISCORD_WEBHOOK_URL"]

def verify_signature(payload: bytes, signature: str) -> bool:
    expected = hmac.new(
        WEBHOOK_SECRET.encode(), payload, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

@app.route("/webhooks/axiora", methods=["POST"])
def handle_webhook():
    signature = request.headers.get("X-Axiora-Webhook-Signature", "")
    event_type = request.headers.get("X-Axiora-Event", "")

    if not verify_signature(request.data, signature):
        abort(401)

    filing = request.json
    company = filing.get("company_name", "Unknown")
    doc_type = filing.get("doc_type_label", "Filing")
    doc_id = filing.get("doc_id", "")
    fiscal_year = filing.get("fiscal_year", "")

    # Discordに投稿
    message = (
        f"📄 **{event_type}**: {company}\n"
        f"種類: {doc_type} (FY{fiscal_year})\n"
        f"Doc: `{doc_id}`\n"
        f"[EDINETで確認](https://disclosure2.edinet-fsa.go.jp/WZEK0040.aspx?S100{doc_id[-4:]})"
    )
    httpx.post(DISCORD_WEBHOOK, json={"content": message})

    return "", 200

署名を検証し、開示データを抽出し、メッセージをフォーマットしてDiscordに投稿。これだけです。

ステップ3:デプロイ

HTTPS POSTを受け付けるサーバーならどこでも動きます:

Railway / Render — GitHubにpushして2分でデプロイ。無料枠あり。

pip install flask httpx gunicorn
gunicorn app:app --bind 0.0.0.0:8000

デプロイ後、公開URLでwebhookを登録:

curl -X POST https://api.axiora.dev/v1/webhooks \
  -H "Authorization: Bearer $AXIORA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.railway.app/webhooks/axiora",
    "events": ["new_filing", "amendment", "correction"]
  }'

Discordへの通知イメージ

トヨタが有価証券報告書を提出すると:

📄 new_filing: トヨタ自動車株式会社 種類: 有価証券報告書 (FY2025) Doc: S100XXXX EDINETで確認

すべての開示、すべての企業。ポーリングなし、cronなし、数分で配信。

署名検証が重要な理由

検証なしでは、webhook URLを知った第三者が偽の開示を送信できます。HMAC-SHA256署名がこれを防ぎます:

  1. 送信前に HMAC-SHA256(リクエストボディ, シークレット) を計算
  2. ダイジェストを X-Axiora-Webhook-Signature ヘッダーに格納
  3. 受信側で同じHMACを再計算し、定数時間比較で照合

hmac.compare_digestによる定数時間比較でタイミング攻撃を防止。Stripe、GitHub、Slackと同じパターンです。

Node.js版:

const crypto = require("crypto");

function verifySignature(body, signature, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(body)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  );
}

Discord以外の活用

webhookペイロードは完全な開示メタデータを含むJSON。構築できるもの:

  • Slack通知 — 同じパターン、URLが違うだけ({"text": "..."}に変更)
  • メールダイジェスト — キューで1時間ごとにバッチ処理し、サマリーメールを送信
  • 自動分析パイプライン — new_filingをトリガーに、APIで財務データを取得し、モデルを実行
  • コンプライアンス監視 — ポートフォリオ内企業のamendment・correctionを追跡。訂正イベントは何かが変わったことを意味する

4,125社以上すべてのwebhookが発火します。ペイロードのフィールド(セクター、企業コード、書類種別)で受信側でフィルタしてください。

関連記事

無料プラン。クレジットカード不要。APIキーを取得 →