30分ごとにAPIを叩いて新着開示を確認する。レート制限を消費して、それでも気づくのは遅い。
Axioraのwebhookはこれを逆転させます。EDINETに新しい開示書類が提出されると、数分以内にあなたのURLにPOSTリクエストを送信。こちらから確認する必要はありません。
このチュートリアルでは、Discordチャンネルに通知を飛ばす仕組みをPython 40行で構築します。
Axiora Webhookの仕組み
3つのイベント:
| イベント | 発火条件 |
|---|---|
new_filing | EDINETから新しい有価証券報告書(年次・半期・四半期)が取り込まれたとき |
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:
S100XXXXEDINETで確認
すべての開示、すべての企業。ポーリングなし、cronなし、数分で配信。
署名検証が重要な理由
検証なしでは、webhook URLを知った第三者が偽の開示を送信できます。HMAC-SHA256署名がこれを防ぎます:
- 送信前に
HMAC-SHA256(リクエストボディ, シークレット)を計算 - ダイジェストを
X-Axiora-Webhook-Signatureヘッダーに格納 - 受信側で同じ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が発火します。ペイロードのフィールド(セクター、企業コード、書類種別)で受信側でフィルタしてください。
関連記事
- 開発者のためのEDINET完全ガイド — 通知される開示書類の中身を理解する
- PythonとStreamlitで日本株スクリーナーを作る — 開示データのUIを構築
無料プラン。クレジットカード不要。APIキーを取得 →